home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir36 / string26.zip / STRINGS.ASM < prev    next >
Assembly Source File  |  1994-07-11  |  189KB  |  5,702 lines

  1.  
  2.                 page    66,132
  3. ;=======================================================================
  4. ; STRINGS.COM - a set of string handling functions for batch files.
  5. ;
  6. ; Syntax:
  7. ;       STRINGS [/H][/M][/Pc ][var = ] function arg1 [, arg2] [, arg3]
  8. ;
  9. ;       /?   - Print help message
  10. ;       /M   - Use master environment block
  11. ;       /Q   - Suppress output to console
  12. ;       /Pc  - Use c as parse character instead of ','
  13. ;       /Bxx - Use xx as for base (base 10 default)
  14. ;       /I   - Install as TSR
  15. ;       /U   - Uninstall 
  16. ;
  17. ; Revision History:
  18. ;
  19. ;  CW   Version 2.6     Fixed bug in findrec_file routine.
  20. ;  CW   Version 2.5     Added GT, GE, LT, and LE commands.
  21. ;  CW   Version 2.4     Fixed incompatibility with SHELLMAX (DOSMAX 2.1).
  22. ;  CW                   Fixed bug with ASK command not accepting spaces.
  23. ;  GS                   Fixed bug with parse_cmdline, it would scan past tail.
  24. ;  CW   Version 2.3     Added DOW and ERRLVL commands.
  25. ;  CW   Version 2.2     Fixed bug with ASK command.
  26. ;  CW   Version 2.1     Fixed bug with READ command.
  27. ;       Version 2.0     New version with many more commands.
  28. ;
  29. ; Table of Initials:
  30. ;
  31. ;  CW   Chad Wagner, 1:369/11.0, chad.wagner@branch.fidonet.org
  32. ;  GS   Gary Smith, 1:226/1210
  33. ;
  34. ;=======================================================================
  35. ;
  36. ;Equates
  37. ;
  38. RES_STACK       equ     offset end_of_resident+512
  39. TRANS_STACK     equ     offset end_of_code+512
  40. VAR_SIZE        equ     128                     ;Max size of variables
  41. DATABUFF_SIZE   equ     2048                    ;Size of file data buffer
  42. MAX_PARAMS      equ     10                      ;Max number of parameters
  43. DEF_PARSE_CHAR  equ     ","                     ;Default parse character
  44.  
  45. ;------------------------------------------------------------------------
  46. ;Code segment
  47. ;------------------------------------------------------------------------
  48.         code    segment
  49.         assume  cs:code
  50.         
  51.         org     2ch
  52. local_environment       dw      ?               ;Word containing the seg
  53.                         ;  of the prog's env. blk.
  54.         org     80h
  55. command_tail    db      ?                       ;Offset of the cmd tail.
  56.  
  57.         org     100h
  58.  
  59. entry:          jmp     initialize
  60. program         db      13,10,"STRINGS "
  61. version         db      "2.6 "
  62. copyright       db      "Copyright 1991, 1992 "
  63.         db      "Douglas Boling",10,13
  64.         db      "First published in PC Magazine,"
  65.         db      " December 29, 1992",13,10,0,"$",1Ah
  66.  
  67.         even                            ;Start data on word bndry
  68. dos_version     dw      0
  69. ems_version     dw      -1
  70. xms_version     dw      -1
  71. databuff_ptr    dw      0                       ;Ptr to file data buffer
  72. saved_ss        dw      0                       ;SS:SP saved on during
  73. saved_sp        dw      0                       ;  multiplex execution
  74. saved_ssint     dw      0                       ;SS:SP saved on during
  75. saved_spint     dw      0                       ;  interrupt function.
  76. int2fh          dd      -1                      ;Old mux int vector
  77. xms_serv        dd      -1                      ;Entry pt for ext mem drvr
  78.  
  79. masterenv_seg   dw      0                       ;Segment of master env
  80. localenv_seg    dw      0                       ;Segment of local env
  81.  
  82. num_params      dw      0                       ;Number of parameters passed
  83. dest_var_val    dw      0
  84. dest_var_name   dw      0                       ;Buffer pointers to parsed
  85. cmd_value       dw      0                       ;  command line variables.
  86. var1_value      dw      0                       ;  These pointers must be
  87. var2_value      dw      0                       ;  kept in this order.
  88. var3_value      dw      0                       
  89. var4_value      dw      0
  90. var5_value      dw      0                      
  91. var6_value      dw      0
  92. var7_value      dw      0
  93. var8_value      dw      0
  94. var9_value      dw      0
  95. var10_value     dw      0
  96.  
  97. number_base     dw      10                      ;Base for num conversion
  98. parse_char      db      DEF_PARSE_CHAR          ;Char used to parse command
  99. quiet_flag      db      0                       ;Flag to suppress output
  100. console_out     db      1                       ;Flag for con out.
  101. use_mastenv     db      0                       ;Flag to use master env
  102. help_flag       db      0                       ;Forces help message
  103. install_flag    db      0                       ;Install as TSR
  104. remove_flag     db      0                       ;Remove
  105. installed       db      0                       ;Installed as TSR flag
  106.  
  107. fill_char       db      " "                     ;Char used to fill zeros
  108. equalsub_char   db      0cdh
  109.  
  110. strings_namelen dw      7                       ;Length of strings name
  111. strings_name    db      "STRINGS",0,0           ;Name of program
  112. shell_var       db      "COMSPEC",0,0           ;Extra zero needed, don't del
  113. shell_name      db      "COMMAND",0,0           ;Cmd shell file name
  114. shell_namlen    db      7                       ;Length of shell filename
  115. ems_header      db      'EMMXXXX0'              ;Expanded mem drvr header
  116. ;
  117. ; Table of command line switches and the corrsponding jump table
  118. ;
  119. cmd_switches    db      "h?mqpbiu"              ;Letters of valid commands.
  120. cmd_switch_end  =       $
  121. cmd_jmp_tbl     dw      offset switch_help      ;This jump table is used to
  122.         dw      offset switch_help      ;  call the routines that
  123.         dw      offset switch_master    ;  process the command line
  124.         dw      offset switch_quiet     ;  arguments
  125.         dw      offset switch_pchar 
  126.         dw      offset switch_base
  127.         dw      offset switch_install
  128.         dw      offset switch_remove
  129. ;
  130. ; Table of commands
  131. ;
  132. command_table   db      "LEFT",0                ;String functions
  133.         db      "RIGHT",0
  134.         db      "MID",0
  135.         db      "LENGTH",0
  136.         db      "FIND",0
  137.         db      "FINDC",0
  138.         db      "LOWER",0
  139.         db      "UPPER",0
  140.         db      "CHAR",0
  141.         db      "VAL",0
  142.         db      "FILEDRIVE",0
  143.         db      "FILEDIR",0
  144.         db      "FILENAME",0
  145.         db      "FILEEXT",0
  146.         db      "PARSE",0
  147.         db      "ADDCOMMAS",0
  148.         db      "REPEAT",0
  149.  
  150.         db      "READ",0                ;File functions
  151.         db      "WRITE",0
  152.         db      "FILESIZE",0
  153.         db      "LINESIZE",0
  154.         db      "TRUENAME",0
  155.         db      "FILEDATE",0            
  156.         db      "FILETIME",0            
  157.                 DB      "ERRLVL",0                                      ;2.3 CW
  158.  
  159.         db      "VER",0                 ;System functions
  160.         db      "ASK",0
  161.         db      "INWIN",0
  162.         db      "2FCHECK",0
  163.         db      "ENVFREE",0
  164.         db      "ENVSIZE",0
  165.         db      "MASTERVAR",0
  166.         db      "LOCALVAR",0
  167.         db      "TRUEVER",0             
  168.         db      "FILES",0               
  169.         db      "LASTDRIVE",0
  170.         db      "CODEPAGE",0
  171.         db      "COUNTRY",0
  172.         db      "BIOSDATE",0
  173.         db      "GETKEY",0
  174.         db      "LOCALENV",0
  175.         db      "MASTERENV",0
  176.  
  177.         db      "ADD",0                 ;Math functions
  178.         db      "SUB",0
  179.         db      "MUL",0
  180.         db      "DIV",0
  181.         db      "AND",0
  182.         db      "OR",0
  183.         db      "XOR",0
  184.         db      "NOT",0
  185.         db      "CONVERT",0
  186.                 DB      "GT",0                                          ;2.5 CW
  187.                 DB      "GE",0                                          ;2.5 CW
  188.                 DB      "LT",0                                          ;2.5 CW
  189.                 DB      "LE",0                                          ;2.5 CW
  190.  
  191.         db      "PEEK",0                ;Progamming functions
  192.         db      "POKE",0
  193.         db      "IN",0
  194.         db      "OUT",0
  195.         db      "INTERRUPT",0
  196.         db      "SCAN",0
  197.  
  198.         db      "DAY",0                 ;Time/Date functions
  199.         db      "MONTH",0
  200.         db      "DATE",0
  201.         db      "TIME",0
  202.                 DB      "DOW",0                                         ;2.3 CW
  203.  
  204.         db      "MEMTOTAL",0            ;Memory status functions
  205.         db      "MEMFREE",0
  206.         db      "XMSTOTAL",0
  207.         db      "XMSFREE",0
  208.         db      "XMSVER",0
  209.         db      "EMSTOTAL",0
  210.         db      "EMSFREE",0
  211.         db      "EMSVER",0
  212.         db      "UMBLARGE",0
  213.  
  214.         db      "STRINGSVER",0          ;Support functions
  215.         db      "INSTALLED",0
  216.         db      "HELP",0
  217.         db      0                       ;End of list flag
  218. ;
  219. ; Jump table for commands
  220. ;
  221. jump_table      dw      offset left_str
  222.         dw      offset right_str
  223.         dw      offset mid_str
  224.         dw      offset length_str
  225.         dw      offset find_str
  226.         dw      offset findc_str
  227.         dw      offset lower_str
  228.         dw      offset upper_str
  229.         dw      offset char_str
  230.         dw      offset val_str
  231.         dw      offset filedrive_str
  232.         dw      offset filedir_str
  233.         dw      offset filename_str
  234.         dw      offset fileext_str
  235.         dw      offset parse_str        ;New
  236.         dw      offset commas_str       ;New
  237.         dw      offset repeat_str       ;New
  238.  
  239.         dw      offset readrec_file
  240.         dw      offset writerec_file
  241.         dw      offset filesize_file
  242.         dw      offset numrec_file
  243.         dw      offset truename_file
  244.         dw      offset filedate_file    ;New
  245.         dw      offset filetime_file    ;New
  246.                 DW      OFFSET errlvl_file                              ;2.3 CW
  247.  
  248.         dw      offset ver_sys
  249.         dw      offset ask2_sys
  250.         dw      offset inwin_sys
  251.         dw      offset int2fcheck_sys
  252.         dw      offset envfree_sys
  253.         dw      offset envsize_sys
  254.         dw      offset mastervar_sys
  255.         dw      offset localvar_sys         
  256.         dw      offset truever_sys      ;New
  257.         dw      offset files_sys        ;New
  258.         dw      offset lastdrive_sys    ;New
  259.         dw      offset codepage_sys     ;New
  260.         dw      offset country_sys      ;New
  261.         dw      offset biosdate_sys     ;New
  262.         dw      offset getkey_sys       ;New
  263.         dw      offset localenv_sys     ;New
  264.         dw      offset masterenv_sys    ;New
  265.  
  266.         dw      offset add_num
  267.         dw      offset sub_num
  268.         dw      offset mul_num
  269.         dw      offset div_num
  270.         dw      offset and_num          ;New
  271.         dw      offset or_num           ;New
  272.         dw      offset xor_num          ;New
  273.         dw      offset not_num          ;New
  274.         dw      offset convert_num      ;New
  275.                 DW      OFFSET gt_num                                   ;2.5 CW
  276.                 DW      OFFSET ge_num                                  ;2.5 CW
  277.                 DW      OFFSET lt_num                                   ;2.5 CW
  278.                 DW      OFFSET le_num                                  ;2.5 CW
  279.  
  280.         dw      offset peek_prog        ;New
  281.         dw      offset poke_prog        ;New
  282.         dw      offset in_prog          ;New
  283.         dw      offset out_prog         ;New
  284.         dw      offset interrupt_prog   ;New
  285.         dw      offset scan_prog        ;New
  286.  
  287.         dw      offset day_time         ;New
  288.         dw      offset month_time       ;New
  289.         dw      offset date_time        ;New
  290.         dw      offset time_time        ;New
  291.                 DW      OFFSET dow_time                                 ;2.3 CW
  292.  
  293.         dw      offset totalmem_mem     ;New
  294.         dw      offset freemem_mem      ;New
  295.         dw      offset totalext_mem     ;New
  296.         dw      offset freeext_mem      ;New
  297.         dw      offset extver_mem       ;New
  298.         dw      offset totalems_mem     ;New
  299.         dw      offset freeems_mem      ;New
  300.         dw      offset emsver_mem       ;New
  301.         dw      offset freeumb_mem      ;New
  302.  
  303.         dw      offset ver_strings      ;New
  304.         dw      offset inst_strings     ;New
  305.         dw      offset help_strings     ;New
  306. jump_table_end  =       $
  307.  
  308. int2fname_tbl   db      "PRINT",0               ;Alias table for multiplex
  309.         db      "ASSIGN",0              ;  interrupt install check
  310.         db      "DRIVER",0
  311.         db      "SHARE",0
  312.         db      "NET",0
  313.         db      "NLS",0
  314.         db      "ANSI",0
  315.         db      "DOSBOX",0
  316.         db      "HIMEM",0
  317.         db      "DOSKEY",0
  318.         db      "DISPLAY",0
  319.         db      "GRAPHTBL",0
  320.         db      "APPEND",0
  321.         db      0                       ;End of list flag
  322.  
  323. int2falias_tbl  db      1                       ;ID numbers of DOS programs
  324.         db      6                       ;  that use the multiplex
  325.         db      8                       ;  interrupt.
  326.         db      10h
  327.         db      11h
  328.         db      14h
  329.         db      1Ah
  330.         db      40h
  331.         db      43h
  332.         db      48h
  333.         db      0ADh
  334.         db      0B0h
  335.         db      0B7h
  336.  
  337.  
  338. day_list        db      "Sunday",0
  339.         db      "Monday",0
  340.         db      "Tuesday",0
  341.         db      "Wednesday",0
  342.         db      "Thursday",0
  343.         db      "Friday",0
  344.         db      "Saturday",0,0
  345.  
  346. month_list      db      "January",0
  347.         db      "February",0
  348.         db      "March",0
  349.         db      "April",0
  350.         db      "May",0
  351.         db      "June",0
  352.         db      "July",0
  353.         db      "August",0
  354.         db      "September",0
  355.         db      "October",0
  356.         db      "November",0
  357.         db      "December",0,0
  358.  
  359. infomsg2        db      "Removed",0             
  360. errmsg0         db      "Need DOS " 
  361. errmsg0ver      db      "2.0"
  362.         db      " or greater",0
  363. errmsg1         db      "Usage: STRINGS [/?][/M][/Q][/Pc][/Bn][/I][/U]"
  364.         db      " [env var =]"
  365.         db      " FUNCTION [Params]",13,10,10
  366.         db      " /M  - Use master environment",13,10
  367.         db      " /Q  - Suppress output to screen",13,10
  368.         db      " /Pc - Use char c instead of ',' as the"
  369.         db      " parse character",13,10
  370.         db      " /Bn - Use n as the number base",13,10
  371.         db      " /I  - Installs as resident code."
  372.         db      " DOS 3.3 or later required",13,10
  373.         db      " /U  - Uninstalls if resident",13,10
  374.         db      10,"For a list of commands type STRINGS /?",0
  375.  
  376. errmsg2         db      "Not enough memory",0
  377. errmsg3         db      "Unknown command line switch",0
  378. errmsg6         db      "Illegal filename",0
  379. errmsg7         db      "Line numbers must be greater than 0",0
  380. errmsg8         db      "Line not found",0
  381.  
  382. errmsg10        db      "Multiply overflow error",0
  383. errmsg11        db      "Divide by zero error",0
  384. errmsg12        db      "Addition overflow",0
  385. errmsg13        db      "Subtraction underflow",0
  386. errmsg14        db      "Number too large",0
  387. errmsg15        db      "Out of environment space",0
  388. errmsg16        db      "Can't find environment",0
  389. errmsg17        db      "No Expanded memory",0
  390. errmsg18        db      "Required parameter missing",0
  391. errmsg19        db      "No Extended memory",0
  392. errmsg20        db      "String not found",0
  393. errmsg21        db      "Not Installed",0
  394. errmsg22        db      "Can",39,"t remove",0
  395. errmsg23        db      "Already installed",0
  396. errmsg24        db      "Base must be within 2-16",0
  397. endmsg          db      13,10,0
  398.  
  399. doserr_tbl      dw      offset  doserr_00
  400.         dw      offset  doserr_00
  401.         dw      offset  doserr_02
  402.         dw      offset  doserr_03
  403.         dw      offset  doserr_04
  404.         dw      offset  doserr_05
  405.         dw      offset  doserr_00
  406.         dw      offset  doserr_07
  407.         dw      offset  doserr_00
  408.         dw      offset  doserr_00
  409.         dw      offset  doserr_10
  410.         dw      offset  doserr_00
  411.         dw      offset  doserr_12
  412.         dw      offset  doserr_13
  413.         dw      offset  doserr_00
  414.         dw      offset  doserr_15
  415.         dw      offset  doserr_00
  416.         dw      offset  doserr_17
  417.         dw      offset  doserr_18
  418.         dw      offset  doserr_19
  419.         dw      offset  doserr_20
  420.         dw      offset  doserr_21
  421.         dw      offset  doserr_22
  422.         dw      offset  doserr_23
  423.         dw      offset  doserr_00
  424.         dw      offset  doserr_25
  425.         dw      offset  doserr_26
  426.         dw      offset  doserr_27
  427.         dw      offset  doserr_00
  428.         dw      offset  doserr_29
  429.         dw      offset  doserr_30
  430.         dw      offset  doserr_31
  431.         dw      offset  doserr_32
  432.         dw      offset  doserr_33
  433.         dw      offset  doserr_34
  434. doserr_tblend   =       $
  435.  
  436. doserr_00       db      "DOS Error",0
  437. doserr_02       db      "File not found",0
  438. doserr_03       db      "Path not found",0
  439. doserr_04       db      "Too many open files",0
  440. doserr_05       db      "Access denied",0
  441. doserr_07       db      "Memory Corrupted",0
  442. doserr_10       db      "Bad Environment block",0
  443. doserr_12       db      "File Access Invalid",0
  444. doserr_13       db      "Data Invalid",0
  445. doserr_15       db      "Not a proper Disk",0
  446. doserr_17       db      "Not same device",0
  447. doserr_18       db      "No more files",0
  448. doserr_19       db      "Disk Write Protected",0
  449. doserr_20       db      "Unknown unit",0
  450. doserr_21       db      "Drive not ready",0
  451. doserr_22       db      "Unknown command",0
  452. doserr_23       db      "CRC Data Error",0
  453. doserr_25       db      "Disk Seek error",0
  454. doserr_26       db      "Not a DOS disk",0
  455. doserr_27       db      "Sector not found",0
  456. doserr_29       db      "File Write fault",0
  457. doserr_30       db      "File Read fault",0
  458. doserr_31       db      "General failure",0
  459. doserr_32       db      "File sharing violation",0
  460. doserr_33       db      "File lock violation",0
  461. doserr_34       db      "Illegal Disk change",0
  462.  
  463. ;============================================================================
  464. ; Multiplex Interrupt handler
  465. ;============================================================================
  466. muxint          proc    far
  467.         assume  cs:code,ds:nothing,es:nothing
  468.         cmp     ax,0ae00h               ;Chk for installed cmd
  469.         je      mux_chkcmd
  470.         cmp     ax,0ae01h               ;Chk for installed cmd
  471.         je      mux_execute
  472. mux_jmp:
  473.         jmp     cs:[int2fh]             ;Jump to old interrupt
  474. mux_installed:
  475.         jmp     short mux_jmp   
  476. ;
  477. ; This routine checks the cmd line for a valid Strings command.
  478. ;
  479. mux_chkcmd:
  480.         cld
  481.         push    cx
  482.         push    di
  483.         push    si
  484.         push    es
  485.         
  486.         lodsb                           ;Load cmd length 
  487.         mov     cl,al
  488.         xor     ch,ch
  489.  
  490.         mov     di,cs                   ;ES:DI points to my cmd
  491.         mov     es,di                   ;  line buff
  492.         mov     di,offset strings_name
  493.         repe    cmpsb
  494.         jne     mux_chk1
  495.         cmp     byte ptr es:[di],0
  496.         jne     mux_chk1
  497.  
  498.         mov     al,-1                   ;Claim command
  499.         mov     di,81h                  ;Copy to my cmd buff
  500.         mov     si,bx                   ;Point to cmd line
  501.         inc     si
  502.         mov     cl,ds:[si]              ;Get length of cmd line
  503.         inc     si                      ;Load cmd line length
  504.         inc     cx
  505.         cmp     cl,7fh                  ;Only allow 127 chars
  506.         ja      mux_chk1
  507.         rep     movsb
  508.         jmp     short mux_chkexit
  509. mux_chk1:
  510.         xor     al,al                   ;Don't want command
  511. mux_chkexit:
  512.         pop     es
  513.         pop     si
  514.         pop     di
  515.         pop     cx
  516.         or      al,al                   ;See if we like cmd
  517.         je      mux_jmp                 ;No, pass on.
  518.         jmp     short mux_iret          ;Yes, return.
  519. ;
  520. ; This routine executes the command line.
  521. ;
  522. mux_execute:
  523.         push    ax
  524.         mov     cs:saved_ss,ss
  525.         mov     cs:saved_sp,sp
  526.         mov     ax,cs
  527.         cli
  528.         mov     ss,ax
  529.         mov     sp,RES_STACK
  530.         sti
  531.  
  532.         push    bx
  533.         push    cx
  534.         push    dx
  535.         push    di
  536.         push    si
  537.         push    bp
  538.         push    ds
  539.         push    es
  540.  
  541.         mov     ax,cs
  542.         mov     ds,ax
  543.         mov     es,ax
  544.         assume  ds:code,es:code
  545.  
  546.         mov     si,offset 81h           ;Remove name of program
  547.         mov     di,si                   ;  from the command 
  548.         xor     bl,bl                   ;  line.  1st, find the
  549.         call    scan4char               ;  name, the move the
  550.         add     si,strings_namelen      ;  ptr past it.
  551.         xor     cx,cx
  552. mux_x1:
  553.         lodsb
  554.         stosb
  555.         inc     cx
  556.         cmp     al,13
  557.         jne     mux_x1
  558.         mov     ds:[80h],cl
  559.  
  560.         call    main                    ;Showtime!
  561.  
  562.         cmp     remove_flag,0           ;See if we should 
  563.         je      mux_xexit               ;  remove the program
  564.         call    remove
  565.         jnc     mux_xexit
  566.         call    print_strcr             ;Print error message
  567. mux_xexit:
  568.         pop     es
  569.         pop     ds
  570.         pop     bp
  571.         pop     si
  572.         pop     di
  573.         pop     dx
  574.         pop     cx
  575.         pop     bx
  576.  
  577.         cli
  578.         mov     ss,cs:saved_ss
  579.         mov     sp,cs:saved_sp
  580.  
  581.         cmp     cs:remove_flag,0        ;If remove, discard
  582.         je      mux_xexit1              ;  mem segment at the
  583.         push    es                      ;  last moment.
  584.         push    cs
  585.         pop     es                      ;Get code segment
  586.         mov     ah,49h                  ;Free mem
  587.         int     21h
  588.         pop     es
  589. mux_xexit1:
  590.         pop     ax
  591.         mov     byte ptr ds:[si],0      ;Tell cmd.com not to ex
  592. mux_iret:
  593.         iret
  594. muxint          endp
  595.  
  596. ;----------------------------------------------------------------------------
  597. ; Start of code.                                                        
  598. ;----------------------------------------------------------------------------
  599. main            proc    near
  600.         assume  cs:code,ds:code,es:code
  601.         cld                             ;Set string operations 'up.'
  602.  
  603.                 call    parse_cmdline           ;Parse command line
  604.         jc      main_error
  605.  
  606.         mov     si,dest_var_name        ;Point to dest env var name
  607.         call    caps_string
  608.  
  609.         mov     si,cmd_value            ;Point to command buffer
  610.         call    caps_string
  611.  
  612.         cmp     help_flag,0             ;If help flag set, call
  613.         je      main_1                  ;  help function to 
  614.         call    help_strings            ;  interpet command.
  615.         jmp     short main_6
  616. main_1:
  617.         inc     cx
  618.         mov     di,offset command_table ;Search cmd table 
  619.         call    findstr
  620.         mov     si,offset errmsg1
  621.         jc      main_error
  622.  
  623.         shl     bx,1                    ;Compute offset of routine to
  624.         call    [bx+offset jump_table]  ;  call, then call routine
  625.         jc      main_error
  626.  
  627.         mov     si,dest_var_val
  628.         cmp     console_out,0           ;See how to return result
  629.         je      main_3
  630.         cmp     byte ptr [si],0         ;If no result, exit
  631.         je      main_6
  632.         call    print_strcr             ;Print result to screen
  633.         jmp     short main_6
  634. main_3:
  635.         mov     di,dest_var_name
  636.         xchg    di,si
  637.  
  638.         call    setenv                  ;Set environemnt variable.
  639.         jc      main_7
  640. main_6:
  641.         xor     al,al                   ;Return code = 0
  642. main_exit:
  643.         ret                             ;Return
  644. ;
  645. ;Display error message.
  646. ;
  647. main_7:
  648.         mov     si,offset errmsg15      ;Out of environment space
  649. main_error:
  650.         push    cs
  651.         pop     ds
  652.         assume  ds:code
  653.  
  654.         push    si
  655.         mov     si,offset program       ;Print copyright msg
  656.         call    print_strcr
  657.         pop     si
  658.         call    print_strcr             ;print string
  659. main_9: 
  660.         mov     al,01                   ;Terminate with RC = 1
  661.         jmp     short main_exit
  662. main            endp
  663.  
  664. ;=============================================================================
  665. ; String Functions
  666. ;=============================================================================
  667. ;-----------------------------------------------------------------------------
  668. ; RIGHT STR  returns the right n characters of the source string
  669. ;-----------------------------------------------------------------------------
  670. right_str       proc    near
  671.         assume  cs:code,ds:code,es:code
  672.         mov     si,var2_value           ;Convert 2nd parameter to hex
  673.         call    asc2hex
  674.         call    truncnum                ;Truncate number to string len
  675.  
  676.         push    ax
  677.         mov     di,var1_value           ;Scan to end of string
  678.         call    find_end
  679.         pop     ax
  680. right_str_2:
  681.         sub     di,ax
  682.         dec     di
  683.         cmp     di,var1_value
  684.         ja      right_str_3
  685.         mov     di,var1_value
  686. right_str_3:
  687.         mov     si,dest_var_val
  688.         xchg    di,si
  689.         call    copy_string             ;Copy string to dest buffer
  690.         clc
  691.         ret
  692. right_str       endp
  693.  
  694. ;-----------------------------------------------------------------------------
  695. ; LEFT STR Returns the left n characters of the source string
  696. ;-----------------------------------------------------------------------------
  697. left_str        proc    near
  698.         assume  cs:code,ds:code,es:code
  699.         mov     si,var2_value           ;Convert 2nd parameter to hex
  700.         call    asc2hex
  701.         call    truncnum                ;Truncate number to string len
  702.  
  703.         mov     si,var1_value
  704.         mov     bx,ax
  705.         mov     byte ptr [si+bx],0
  706.  
  707.         mov     di,dest_var_val
  708.         call    copy_string             ;Copy string to dest buffer
  709.         clc
  710.         ret
  711. left_str        endp
  712.  
  713. ;-----------------------------------------------------------------------------
  714. ; MID STR Returns a string of n characters starting m characters from the
  715. ;         left of the source string
  716. ;-----------------------------------------------------------------------------
  717. mid_str         proc    near
  718.         assume  cs:code,ds:code,es:code
  719.         mov     si,var2_value           ;Convert 2nd parameter to hex
  720.         call    asc2hex
  721.         dec     ax
  722.         call    truncnum                ;Truncate num
  723.         mov     cx,ax                   ;Copy second parameter
  724.  
  725.         mov     si,var3_value           ;Convert 3rd param to hex
  726.         cmp     byte ptr [si],0         ;See if no parameter
  727.         je      mid_str_0
  728.         call    asc2hex                 ;If no number, return max
  729.         jnc     mid_str_1               ;  value to insure remainder
  730. mid_str_0:
  731.         mov     ax,VAR_SIZE             ;  of string returned.
  732. mid_str_1:
  733.         call    truncnum                ;Truncate num
  734.  
  735.         push    ax                      ;Save length of substring
  736.         xor     ax,ax
  737.         cmp     al,1                    ;Clear zero flag
  738.         mov     di,var1_value           ;Scan to new start of string
  739.         jcxz    mid_str_11
  740.         repne   scasb
  741. mid_str_11:
  742.         pop     cx                      ;Pop length of substring
  743.         mov     si,di                   ;Copy ptr to start of substr
  744.         je      mid_str_2               ;If end of str found, end
  745.  
  746.         repne   scasb                   ;Scan until end of substring
  747.         mov     byte ptr [di],0
  748. mid_str_2:
  749.         mov     di,dest_var_val
  750.         call    copy_string             ;Copy string to dest buffer
  751.         clc
  752.         ret
  753. mid_str         endp
  754.  
  755. ;-----------------------------------------------------------------------------
  756. ; LENGTH STR Computes the length of the source string
  757. ;-----------------------------------------------------------------------------
  758. length_str      proc    near
  759.         assume  cs:code,ds:code,es:code
  760.         mov     di,var1_value           ;Find_end also returns the
  761.         call    find_end                ;  length of the string in
  762.         mov     ax,cx                   ;  CX.
  763.         xor     dx,dx
  764.         mov     di,dest_var_val         ;Convert value to ASCII
  765.         call    hex2asc
  766.         clc
  767.         ret
  768. length_str      endp
  769.  
  770. ;-----------------------------------------------------------------------------
  771. ; UPPER STR Convert the source string to upper case
  772. ;-----------------------------------------------------------------------------
  773. upper_str       proc    near
  774.         assume  cs:code,ds:code,es:code
  775.         mov     di,dest_var_val
  776.         mov     si,var1_value
  777.         push    di
  778.         call    copy_string             ;Copy string to dest buffer
  779.         pop     si
  780.         call    caps_string             ;Convert to upper case.
  781.         clc
  782.         ret
  783. upper_str       endp
  784.  
  785. ;-----------------------------------------------------------------------------
  786. ; LOWER STR Convert the source string to lower case
  787. ;-----------------------------------------------------------------------------
  788. lower_str       proc    near
  789.         assume  cs:code,ds:code,es:code
  790.         mov     di,dest_var_val
  791.         mov     si,var1_value
  792.         push    di
  793.         call    copy_string             ;Copy string to dest buffer
  794.         pop     si
  795.         call    lc_string               ;Convert to lower case.
  796.         clc
  797.         ret
  798. lower_str       endp
  799.  
  800. ;-----------------------------------------------------------------------------
  801. ; CHAR STR Convert the source number to a ASCII character
  802. ; Revised in ver 2.0 to handle up to 10 numbers
  803. ;-----------------------------------------------------------------------------
  804. char_str        proc    near
  805.         assume  cs:code,ds:code,es:code
  806.         push    bp
  807.         mov     di,dest_var_val         ;Get ptr to output buff
  808.         mov     bp,offset var1_value    ;Get ptr to var array
  809.         mov     cx,num_params           ;Get number of parameters
  810.         or      cx,cx
  811.         jne     charstr_1               
  812.         mov     cx,1
  813. charstr_1:
  814.         mov     si,[bp]                 ;Get ptr to variable
  815.         inc     bp                      ;Point BP to next var
  816.         inc     bp
  817.         call    asc2hex                 ;Convert ASCII num to
  818.         stosb                           ;  hex num and store.
  819.         loop    charstr_1
  820.         xor     al,al                   ;Write number directly to
  821.         stosb                           ;  dest string.  Include
  822.         clc                             ;  zero for termination.
  823.         pop     bp
  824.         ret
  825. char_str        endp
  826.  
  827. ;-----------------------------------------------------------------------------
  828. ; VAL STR Convert the source character to its HEX equivalent
  829. ; Revised in ver 2.0 to handle more than one character
  830. ;-----------------------------------------------------------------------------
  831. val_str         proc    near
  832.         assume  cs:code,ds:code,es:code
  833.         mov     di,dest_var_val         ;Get ptr to output buff
  834.         mov     si,var1_value           ;Get ptr to char string
  835. valstr_1:
  836.         lodsb                           ;Get character
  837.         or      al,al
  838.         je      valstr_2
  839.         xor     ah,ah
  840.         xor     dx,dx
  841.         call    hex2asc                 ;Convert character to
  842.         mov     byte ptr [di-1],' '     ;  ascii num and store.
  843.         jmp     short valstr_1
  844.         dec     di
  845. valstr_2:
  846.         xor     al,al                   ;Write number directly to
  847.         stosb                           ;  dest string.  Include
  848.         clc                             ;  zero for termination.
  849.         ret
  850. val_str         endp
  851.  
  852. ;-----------------------------------------------------------------------------
  853. ; FILEDRIVE STR Return only the directory from a filename string
  854. ;-----------------------------------------------------------------------------
  855. filedrive_str   proc    near
  856.         assume  cs:code,ds:code,es:code
  857.         mov     si,var1_value           ;Fully qualify filename
  858.         mov     di,dest_var_val         ;Point string to dest buff
  859.         call    parse_filename
  860.         mov     byte ptr [di+2],0       ;Terminate after drive spec
  861.         clc
  862.         ret
  863. filedrive_str   endp
  864.  
  865. ;-----------------------------------------------------------------------------
  866. ; FILEDIR STR Return only the directory from a filename string
  867. ;-----------------------------------------------------------------------------
  868. filedir_str     proc    near
  869.         assume  cs:code,ds:code,es:code
  870.         mov     si,var1_value           ;Fully qualify filename
  871.         mov     di,var2_value           ;Use 2nd buff as temp buff
  872.         call    parse_filename
  873.         mov     si,dest_var_val
  874.         xchg    si,di
  875.         add     si,2                    ;Skip past drive stuff
  876.         mov     bx,di
  877.         mov     dx,bx
  878.         inc     dx
  879. filedir_1:
  880.         lodsb
  881.         stosb
  882.         cmp     al,'\'                  ;Mark start of filename or
  883.         jne     filedir_2               ;  directory.
  884.         mov     bx,di
  885. filedir_2:
  886.         or      al,al                   ;See if at end of string
  887.         je      filedir_3
  888.         cmp     al,'.'                  ;See if file ext found
  889.         jne     filedir_1
  890. filedir_3:
  891.         cmp     bx,dx                   ;If root dir, don't delete
  892.         je      filedir_4               ;  lone \.
  893.         dec     bx
  894. filedir_4:
  895.         mov     byte ptr [bx],0         ;Terminate string at end of
  896.         clc                             ;  directory
  897.         ret
  898. filedir_str     endp
  899.  
  900. ;-----------------------------------------------------------------------------
  901. ; FILENAME STR Return only the filename from a filename string
  902. ;-----------------------------------------------------------------------------
  903. filename_str    proc    near
  904.         assume  cs:code,ds:code,es:code
  905.         mov     si,var1_value           ;Fully qualify filename
  906.         mov     di,var2_value           ;Use 2nd buff as temp buff
  907.         call    get_filename
  908.         mov     di,dest_var_val         ;Pt to dest buff
  909.         rep     movsb
  910.         xor     al,al                   ;Terminate filename and
  911.         stosb                           ;  clear error flag
  912.         ret
  913. filename_str    endp
  914.  
  915. ;-----------------------------------------------------------------------------
  916. ; FILEEXT STR Return only the filename extension from a filename string
  917. ;-----------------------------------------------------------------------------
  918. fileext_str     proc    near
  919.         assume  cs:code,ds:code,es:code
  920.         mov     si,var1_value           ;Fully qualify filename
  921.         mov     di,var2_value           ;Use 2nd buff as temp buff
  922.         call    parse_filename
  923.         mov     si,di
  924.         xor     bx,bx
  925. fileext_1:
  926.         lodsb
  927.         cmp     al,'.'                  ;Mark start of filename or
  928.         jne     fileext_2               ;  directory.
  929.         mov     bx,si
  930. fileext_2:
  931.         or      al,al
  932.         jne     fileext_1
  933.  
  934.         or      bx,bx
  935.         je      fileext_3
  936.         mov     cx,si
  937.         sub     cx,bx                   ;Compute length
  938.         mov     di,dest_var_val
  939.         mov     si,bx
  940.         rep     movsb
  941.         xor     al,al                   ;Terminate string
  942.         stosb
  943. fileext_3:
  944.         clc
  945.         ret
  946. fileext_str     endp
  947.  
  948. ;-----------------------------------------------------------------------------
  949. ; FIND STR  finds a string within another string.
  950. ; Exit:      AL - Return code if string not found
  951. ;            CF - Set if string not found
  952. ;-----------------------------------------------------------------------------
  953. find_str        proc    near
  954.         mov     si,var1_value           ;To ignore case, capitalize
  955.         call    caps_string             ;  both strings, then call
  956.         mov     si,var2_value           ;  the findc function.
  957.         call    caps_string
  958.         call    findc_str
  959.         ret
  960. find_str        endp
  961.  
  962. ;-----------------------------------------------------------------------------
  963. ; FINDC STR  finds a string within another string, respects case.
  964. ; Exit:      AL - Return code if string not found
  965. ;            CF - Set if string not found
  966. ;-----------------------------------------------------------------------------
  967. findc_str       proc    near
  968.         mov     di,var1_value           ;Get ptr to 1st string
  969.         push    di
  970.         call    find_end                ;Compute length
  971.         pop     si
  972.         push    cx                      ;Save length
  973.         mov     di,var2_value
  974.         mov     dx,di
  975.         call    find_end
  976.         mov     bx,cx                   ;Save length of search string
  977.         pop     cx                      ;Restore length of trg string
  978.         sub     cx,bx                   ;Sub length of search string.
  979.         jb      find_str_not_found
  980.         inc     cx
  981. find_str_1:
  982.         push    cx
  983.         mov     cx,bx                   ;Restore search str length
  984.         mov     di,dx                   ;Restore ptr to search str
  985.         push    si
  986.         repe    cmpsb                   ;Compare command
  987.         pop     si
  988.         pop     cx
  989.         je      find_str_found
  990.         inc     si                      ;Inc target string ptr
  991.         loop    find_str_1
  992. find_str_not_found:
  993.         xor     ax,ax                   ;Set bad return code
  994.         jmp     short find_str_2
  995. find_str_found:
  996.         mov     ax,si                   ;Copy offset
  997.         sub     ax,var1_value           ;Sub starting offset
  998.         inc     ax
  999. find_str_2:
  1000.         xor     dx,dx
  1001.         mov     di,dest_var_val         ;Convert value to ASCII
  1002.         call    hex2asc
  1003.         clc
  1004. find_str_exit:
  1005.         ret
  1006. findc_str       endp
  1007.  
  1008. ;-----------------------------------------------------------------------------
  1009. ; PARSE STR  Returns the nth token in a string
  1010. ;-----------------------------------------------------------------------------
  1011. parse_str       proc    near
  1012.         assume  cs:code,ds:code,es:code
  1013.         mov     si,var2_value           ;Convert 2nd param to hex
  1014.         call    asc2hex
  1015.         mov     di,100h
  1016.         mov     cx,ax                   ;Save count
  1017.         sub     cx,1
  1018.         jb      parse_str_3
  1019.         mov     bx,var3_value
  1020.         mov     dl,[bx]                 ;Get parse char
  1021.         or      dl,dl
  1022.         jne     parse_str_0
  1023.         mov     dl,' '
  1024. parse_str_0:
  1025.         mov     si,var1_value           ;Get ptr to string
  1026.         or      cx,cx                   ;Check count for 0
  1027.         je      parse_str_2
  1028. parse_str_1:
  1029.         mov     bl,4                    ;Scan for char in DL
  1030.         call    scan4char
  1031.         jc      parse_str_exit
  1032.         inc     si
  1033.         loop    parse_str_1
  1034. parse_str_2:
  1035.         mov     di,si
  1036.         mov     bl,4                    ;Scan for char in DL
  1037.         call    scan4char
  1038.         mov     byte ptr [si],0         ;Term string
  1039. parse_str_3:
  1040.         mov     si,dest_var_val         ;Get ptr to output buff
  1041.         xchg    si,di
  1042.         call    copy_string
  1043. parse_str_exit:
  1044.         clc
  1045.         ret
  1046. parse_str       endp
  1047.  
  1048. ;-----------------------------------------------------------------------------
  1049. ; COMMAS STR  Returns the nth token in a string
  1050. ;-----------------------------------------------------------------------------
  1051. commas_str      proc    near
  1052.         assume  cs:code,ds:code,es:code
  1053.         mov     di,var1_value
  1054.         call    find_end
  1055.         mov     ax,cx
  1056.         mov     cl,3
  1057.         div     cl
  1058.         mov     cl,ah                   ;Copy remainder
  1059.         xor     ch,ch
  1060.         mov     ah,al                   ;Save quotient
  1061.         mov     al,','
  1062.  
  1063.         mov     si,var1_value
  1064.         mov     di,dest_var_val         ;Get ptr to output buff
  1065.         jcxz    commas_1
  1066.         rep     movsb
  1067.         jmp     commas_2
  1068. commas_1:
  1069.         mov     cl,ah
  1070.         jcxz    commas_str_exit
  1071.         jmp     short commas_4
  1072.         
  1073. commas_2:
  1074.         mov     cl,ah                   ;Get number of commas
  1075.         jcxz    commas_str_exit
  1076. commas_3:
  1077.         stosb                           ;Insert comma
  1078. commas_4:
  1079.         movsw                           ;Copy 3 digits
  1080.         movsb
  1081.         loop    commas_3
  1082. commas_str_exit:
  1083.         xor     al,al
  1084.         stosb
  1085.         clc
  1086.         ret
  1087. commas_str      endp
  1088.  
  1089. ;-----------------------------------------------------------------------------
  1090. ; REPEAT STR  Returns a string with n number of a character
  1091. ;-----------------------------------------------------------------------------
  1092. repeat_str      proc    near
  1093.         assume  cs:code,ds:code,es:code
  1094.         mov     si,var2_value           ;Get character to repeat
  1095.         mov     al,[si]
  1096.         push    ax
  1097.         mov     si,var1_value           ;Convert 2nd param to hex
  1098.         call    asc2hex
  1099.         mov     cx,ax
  1100.         pop     ax                      ;Get back repeat char
  1101.         or      dx,dx
  1102.         jne     repeat_error            ;See if repeat number too
  1103.         cmp     cx,VAR_SIZE             ;  big.
  1104.         jae     repeat_error
  1105.         mov     di,dest_var_val
  1106.         rep     stosb
  1107.         xor     al,al
  1108.         stosb
  1109.         clc
  1110. repeat_exit:
  1111.         ret
  1112. repeat_error:
  1113.         mov si,offset errmsg14          ;Number too large
  1114.         stc
  1115.         jmp     short repeat_exit
  1116. repeat_str      endp
  1117.  
  1118. ;=============================================================================
  1119. ; File Functions
  1120. ;=============================================================================
  1121. ;-----------------------------------------------------------------------------
  1122. ; READ REC returns record n from a file.
  1123. ;-----------------------------------------------------------------------------
  1124. readrec_file    proc    near
  1125.         assume  cs:code,ds:code,es:code
  1126.  
  1127.         mov     si,var1_value           ;Fully qualify filename
  1128.         mov     di,dest_var_val         ;Use dest buff as temp buff
  1129.         call    parse_filename
  1130.         mov     dx,di                   ;Copy filename pointer
  1131.         xor     al,al                   ;Read only access
  1132.         call    open_file
  1133.         jc      readrec_error
  1134.  
  1135.         mov     si,var2_value           ;Convert 2nd param to record
  1136.         call    asc2hex                 ;  number.
  1137.  
  1138.         call    findrec_file            ;Find record.
  1139.         mov     ax,si                   ;Copy end of file flag.
  1140.         mov     si,offset errmsg8       ;Record not found.
  1141.         jc      readrec_error1          ;Error if record not found.
  1142.  
  1143.         mov     si,dest_var_val
  1144.         xchg    di,si
  1145.         jcxz    readrec_2
  1146. readrec_1:
  1147.         lodsb                           ;Copy record to destination
  1148.         cmp     al,13                   ;  buffer.
  1149.         je      readrec_3
  1150.         stosb
  1151.         loop    readrec_1
  1152. readrec_2:
  1153.         or      ah,ah                   ;Check end of file flag
  1154.         jne     readrec_3
  1155.         mov     dx,databuff_ptr         ;If at end of data buffer.
  1156.         mov     cx,VAR_SIZE             ;  read enough to complete
  1157.         call    read_file               ;  record.
  1158.         jc      readrec_error
  1159.         mov     cx,ax                   ;Copy number of bytes read.
  1160.         mov     di,dx
  1161.         jmp     short readrec_1
  1162. readrec_3:
  1163.         xor     al,al                   ;Append terminating zero
  1164.         stosb
  1165.         call    close_file              ;Close file
  1166.         jc      readrec_error
  1167. readrec_exit:
  1168.         ret
  1169. readrec_error:
  1170.         call    parse_doserr
  1171.         jmp     short readrec_exit
  1172. readrec_error1:
  1173.         call    close_file
  1174.         stc
  1175.         jmp     short readrec_exit
  1176. readrec_file    endp
  1177.  
  1178. ;-----------------------------------------------------------------------------
  1179. ; WRITE REC appends a string to the end of a file.
  1180. ;-----------------------------------------------------------------------------
  1181. writerec_file   proc    near
  1182.         assume  cs:code,ds:code,es:code
  1183.  
  1184.         mov     si,var1_value           ;Fully qualify filename
  1185.         mov     di,dest_var_val         ;Use dest buff as temp buff
  1186.         call    parse_filename
  1187.         mov     dx,di                   ;Copy filename pointer
  1188.         mov     al,2                    ;Read/Write Access
  1189.         call    open_file               ;Open file.  If file does not
  1190.         jnc     writerec_0              ;  exist, create the file.
  1191.         call    create_file
  1192.         jc      writerec_error
  1193.         mov     si,1
  1194.         jmp     short writerec_1
  1195. writerec_0:
  1196.         xor     ax,ax                   ;Move file ptr to end of file
  1197.         cwd
  1198.         mov     cx,2                    ;Move pointer from end.
  1199.         call    move_fileptr            ;Move file pointer
  1200.         jc      writerec_error
  1201.         mov     si,1
  1202.         or      dx,dx
  1203.         jne     writerec_01
  1204.         or      ax,ax
  1205.         je      writerec_1
  1206. writerec_01:
  1207.         mov     ax,-1                   ;Move file ptr to last byte
  1208.         cwd
  1209.         mov     cx,2                    ;Move pointer from end.
  1210.         call    move_fileptr            ;Move file pointer
  1211.         jc      writerec_error
  1212.         dec     si                      ;Clear EOF marker flag
  1213.     
  1214.         mov     dx,dest_var_val         ;Read last char to check for
  1215.         mov     cx,1                    ;  EOF marker
  1216.         call    read_file
  1217.         jc      writerec_error
  1218.  
  1219.         mov     di,dx
  1220.         cmp     byte ptr [di],1Ah
  1221.         jne     writerec_1
  1222.  
  1223.         mov     ax,-1                   ;See if last byte 1A EOF mark
  1224.         cwd
  1225.         mov     cx,2                    ;Move pointer from end.
  1226.         call    move_fileptr            ;Move file pointer
  1227.         jc      writerec_error
  1228.         inc     si                      ;Set EOF marker flag
  1229. writerec_1:
  1230.         mov     di,var2_value           ;Get length of string
  1231.         mov     dx,di
  1232.         call    find_end
  1233.         dec     di                      ;Backup before zero
  1234.         mov     ax,0a0dh
  1235.         stosw
  1236.         inc     cx
  1237.         inc     cx
  1238.         or      si,si
  1239.         je      writerec_2
  1240.         mov     al,1ah                  ;Append EOF marker
  1241.         stosb
  1242.         inc     cx
  1243. writerec_2:
  1244.         call    write_file
  1245.         jc      writerec_error
  1246.  
  1247.         call    close_file              ;Close file
  1248.         jc      writerec_error
  1249. writerec_exit:
  1250.         mov     di,dest_var_val         ;Clear dest value.
  1251.         mov     byte ptr [di],0
  1252.         ret
  1253. writerec_error:
  1254.         call    parse_doserr            ;Get msg for DOS error
  1255.         jmp     short writerec_exit
  1256. writerec_error1:
  1257.         call    close_file
  1258.         stc
  1259.         jmp     short writerec_exit
  1260. writerec_file   endp
  1261.  
  1262. ;-----------------------------------------------------------------------------
  1263. ; NUMREC FILE returns the number of records in a file.
  1264. ;-----------------------------------------------------------------------------
  1265. numrec_file     proc    near
  1266.         assume  cs:code,ds:code,es:code
  1267.  
  1268.         mov     si,var1_value           ;Fully qualify filename
  1269.         mov     di,dest_var_val         ;Use dest buff as temp buff
  1270.         call    parse_filename
  1271.         mov     dx,di                   ;Copy filename pointer
  1272.         xor     al,al                   ;Read only access
  1273.         call    open_file
  1274.         jc      numrec_error
  1275.  
  1276.         xor     ax,ax                   ;Attempt to find large rec num
  1277.         mov     dx,ax
  1278.  
  1279.         call    findrec_file            ;Find record.
  1280.         jnc     numrec_error1           ;Error if record found.
  1281.  
  1282.         not     ax                      ;Compliment line count.  No
  1283.         not     dx                      ;  need to add 1 since count
  1284.                         ;  already 1 too many.
  1285.         mov     di,dest_var_val         ;Convert rec number to ASCII
  1286.         call    hex2asc
  1287.  
  1288.         call    close_file              ;Close file
  1289.         jc      numrec_error
  1290. numrec_exit:
  1291.         ret
  1292. numrec_error:
  1293.         call    parse_doserr            ;Get msg for DOS error
  1294.         jmp     short numrec_exit
  1295. numrec_error1:
  1296.         call    close_file
  1297.         jc      numrec_error
  1298.         stc
  1299.         jmp     short numrec_exit
  1300. numrec_file     endp
  1301.  
  1302. ;-----------------------------------------------------------------------------
  1303. ; FIND REC returns an offset to the Nth record of a file.
  1304. ; Entry: DX,AX - Record to find
  1305. ;        BX - Source File handle
  1306. ; Exit:  DX,AX - Records remaing if end of file
  1307. ;        CF - Set if record not found.
  1308. ;        DI - Points to record.
  1309. ;        CX - Number of bytes to end of data buffer
  1310. ;        SI - Points to error message if CF set.
  1311. ;-----------------------------------------------------------------------------
  1312. findrec_numl    equ     word ptr [bp-2]
  1313. findrec_numh    equ     word ptr [bp-4]
  1314. findrec_eof     equ     byte ptr [bp-5]
  1315. findrec_file    proc    near
  1316.         assume  cs:code,ds:code,es:code
  1317.         push    bp
  1318.         mov     bp,sp
  1319.         sub     sp,6
  1320.  
  1321.         mov     si,offset errmsg8       ;Record not found
  1322.         mov     findrec_eof,0           ;Clear end of file flag.
  1323.         mov     findrec_numl,ax         ;Save record number.
  1324.         mov     findrec_numh,dx
  1325. findrec_1:
  1326.         mov     cx,databuff_ptr
  1327.         xchg    cx,dx
  1328.  
  1329.         mov     cx,DATABUFF_SIZE        ;Get size of data buffer
  1330.                 call    read_file               ;Read data from file.   ;2.6
  1331.         jc      findrec_error
  1332.  
  1333. findrec_1a:     cmp     ax,cx                   ;See if buffer filled.  If
  1334.         je      findrec_2               ;  not, end of file.
  1335.         mov     findrec_eof,1           ;Set end of file flag.
  1336. findrec_2:
  1337.         mov     cx,ax                   ;Copy num bytes read.
  1338.         mov     di,dx                   ;Copy buffer ptr
  1339.         mov     dx,ax                   ;Save size of buffer
  1340.  
  1341.         mov     al,13                   ;Scan for CR
  1342. findrec_3:
  1343.         sub     findrec_numl,1          ;Decriment record count
  1344.         sbb     findrec_numh,0
  1345.  
  1346.         jne     findrec_4               ;See if record count = 0
  1347.         cmp     findrec_numl,0
  1348.         je      findrec_5
  1349. findrec_4:
  1350.         repne   scasb
  1351.                 je      findrec_7                                       ;2.6
  1352.         cmp     findrec_eof,1           ;If end of buffer, see if
  1353.         jne     findrec_1               ;  end of file. Yes = exit
  1354.         stc
  1355.         jmp     short findrec_exit
  1356.  
  1357. findrec_7:
  1358.                 push    di                                              ;2.6
  1359.                 push    cx                                              ;2.6
  1360.                 repne   scasb                                           ;2.6
  1361.                 pop     cx                                              ;2.6
  1362.                 pop     di                                              ;2.6
  1363.                 je      findrec_3                                       ;2.6
  1364.  
  1365.                 cmp     findrec_eof,1                                   ;2.6
  1366.                 je      findrec_3                                       ;2.6
  1367.  
  1368.                 cmp     byte ptr [di],0ah                               ;2.6
  1369.                 jne     findrec_8                                       ;2.6
  1370.                 inc     di                                              ;2.6
  1371.                 dec     cx                                              ;2.6
  1372.  
  1373. findrec_8:      push    di                                              ;2.6
  1374.                 pop     si                                              ;2.6
  1375.                 mov     di,databuff_ptr                                 ;2.6
  1376.                 push    cx                                              ;2.6
  1377.                 push    cx                                              ;2.6
  1378.                 rep     movsb                                           ;2.6
  1379.                 pop     cx                                              ;2.6
  1380.  
  1381.                 mov     dx,di                                           ;2.6
  1382.                 mov     ax,DATABUFF_size                                ;2.6
  1383.                 sub     ax,cx                                           ;2.6
  1384.                 mov     cx,ax                                           ;2.6
  1385.                 call    read_file               ;Read data from file.   ;2.6
  1386.                 jc      findrec_error                                   ;2.6
  1387.                 pop     dx                                              ;2.6
  1388.                 add     ax,dx                                           ;2.6
  1389.                 mov     dx,databuff_ptr                                 ;2.6
  1390.                 jmp     short findrec_1a                                ;2.6
  1391. findrec_5:
  1392.         cmp     byte ptr [di],0ah       ;discard Line feed
  1393.         jne     findrec_6
  1394.         inc     di
  1395.         dec     cx
  1396. findrec_6:
  1397. ;               call    close_file              ;Close file             ;2.0 CW
  1398. ;               jc      findrec_error                                   ;2.0 CW
  1399.         clc
  1400. findrec_exit:
  1401.         mov     ah,findrec_eof
  1402.         mov     al,0
  1403.         mov     si,ax                   ;Save end of file flag
  1404.  
  1405.         mov     ax,findrec_numl         ;Get record number.
  1406.         mov     dx,findrec_numh
  1407.  
  1408.         mov     sp,bp
  1409.         pop     bp
  1410.         ret
  1411. findrec_error:
  1412.         call    parse_doserr            ;Get msg for DOS error
  1413. findrec_error1:
  1414.         stc
  1415.         jmp     short findrec_exit
  1416. findrec_file    endp
  1417.  
  1418. ;-----------------------------------------------------------------------------
  1419. ; FILE SIZE  returns the size of a file
  1420. ;-----------------------------------------------------------------------------
  1421. filesize_file   proc    near
  1422.         assume  cs:code,ds:code,es:code
  1423.         mov     si,var1_value           ;Fully qualify filename
  1424.         mov     di,dest_var_val         ;Use dest buff as temp buff
  1425.         call    parse_filename
  1426.         mov     dx,di                   ;Copy filename pointer
  1427.         xor     al,al                   ;Read only access
  1428.         call    open_file
  1429.         mov     di,dest_var_val         ;Point DI to result buffer.
  1430.         jc      filesize_error
  1431.  
  1432.         xor     ax,ax                   ;Zero offset.
  1433.         xor     dx,dx
  1434.         mov     cl,2                    ;Move pointer from end.
  1435.         call    move_fileptr            ;Move file pointer
  1436.         jc      filesize_error
  1437.  
  1438.         call    hex2asc                 ;Convert size to ASCII
  1439.         call    close_file              ;Close file
  1440.         jc      filesize_error
  1441. filesize_exit:
  1442.         ret
  1443. filesize_error:
  1444.         call    parse_doserr            ;Get msg for DOS error
  1445.         jmp     short filesize_exit             
  1446. filesize_file   endp
  1447.  
  1448. ;-----------------------------------------------------------------------------
  1449. ; TRUENAME FILE  returns the fully qualified name of a file.
  1450. ;-----------------------------------------------------------------------------
  1451. truename_file   proc    near
  1452.         assume  cs:code,ds:code,es:code
  1453.         mov     si,var1_value           ;Fully qualify filename
  1454.         mov     di,dest_var_val         ;Use dest buff as temp buff
  1455.         call    parse_filename
  1456.         jnc     truename_1
  1457.         mov     si,offset errmsg6       ;Illegal filename msg
  1458. truename_1:
  1459.         ret
  1460. truename_file   endp
  1461.  
  1462. ;-----------------------------------------------------------------------------
  1463. ; FILE DATE  returns the date of a file
  1464. ;-----------------------------------------------------------------------------
  1465. filedate_file   proc    near
  1466.         assume  cs:code,ds:code,es:code
  1467.         mov     si,var1_value           ;Fully qualify filename
  1468.         mov     di,dest_var_val         ;Use dest buff as temp buff
  1469.         call    parse_filename
  1470.         mov     dx,di                   ;Copy filename pointer
  1471.  
  1472.         xor     al,al                   ;Read only access
  1473.         call    open_file
  1474.         jc      filedate_error
  1475.  
  1476.         mov     ax,5700h                ;Get file date/time
  1477.         int     21h
  1478.         jc      filedate_error
  1479.         push    bx                      ;Save file handle
  1480.  
  1481.         mov     ax,dx                   ;DX: yyyy yyym mmmd dddd
  1482.         shl     dx,1
  1483.         shl     dx,1
  1484.         shl     dx,1
  1485.         mov     dl,al                   ;DH:Months, DL:days 
  1486.         and     dx,0f1fh                ;Clear off unneeded bits
  1487.         shr     ah,1                    ;Align years
  1488.         mov     cx,1980                 ;Set starting year
  1489.         add     cl,ah                   ;This fails in year 2048
  1490.         mov     di,dest_var_val
  1491.         call    print_date              ;Write date
  1492.  
  1493.         pop     bx                      ;Restore file handle
  1494.         call    close_file              ;Close file
  1495.         jc      filedate_error
  1496. filedate_exit:
  1497.         ret
  1498. filedate_error:
  1499.         call    parse_doserr            ;Get msg for DOS error
  1500.         jmp     short filedate_exit             
  1501. filedate_file   endp
  1502.  
  1503. ;-----------------------------------------------------------------------------
  1504. ; FILE TIME  returns the time of a file
  1505. ;-----------------------------------------------------------------------------
  1506. filetime_file   proc    near
  1507.         assume  cs:code,ds:code,es:code
  1508.         mov     si,var1_value           ;Fully qualify filename
  1509.         mov     di,dest_var_val         ;Use dest buff as temp buff
  1510.         call    parse_filename
  1511.         mov     dx,di                   ;Copy filename pointer
  1512.  
  1513.         xor     al,al                   ;Read only access
  1514.         call    open_file
  1515.         jc      filetime_error
  1516.  
  1517.         mov     ax,5700h                ;Get file date/time
  1518.         int     21h
  1519.         jc      filetime_error
  1520.         push    bx                      ;Save file handle
  1521.         mov     dh,cl                   ;CX: hhhh hmmm mmms ssss
  1522.         shl     dh,1                    ;Mul seconds by 2
  1523.         and     dh,3fh                  ;Mask off other bits
  1524.  
  1525.         rol     cx,1                    ;Roll hours to low byte
  1526.         rol     cx,1                    ;  but stop at 3 to
  1527.         rol     cx,1                    ;  copy now aligned 
  1528.         mov     al,ch                   ;  minute bits.
  1529.  
  1530.         rol     cx,1
  1531.         rol     cx,1
  1532.         mov     ch,al                   ;Get back minutes
  1533.         xchg    ch,cl
  1534.         and     cx,1f3fh                ;Mask off sec bits
  1535.  
  1536.         mov     di,dest_var_val
  1537.         call    print_time
  1538.  
  1539.         pop     bx                      ;Restore file handle
  1540.         call    close_file              ;Close file
  1541.         jc      filetime_error
  1542. filetime_exit:
  1543.         ret
  1544. filetime_error:
  1545.         call    parse_doserr            ;Get msg for DOS error
  1546.         jmp     short filetime_exit             
  1547. filetime_file   endp
  1548.  
  1549. ;-----------------------------------------------------------------------------
  1550. ; ERRLVL  returns the errorlevel of a file
  1551. ;-----------------------------------------------------------------------------
  1552. execParmBlock   DW      0               ;Use our environment
  1553.         DD      0               ;Command tail
  1554.         DD      0               ;Pointer to first FCB
  1555.         DD      0               ;Pointer to second FCB
  1556.  
  1557. errlvl_file     PROC    NEAR
  1558.         ASSUME  CS:CODE,DS:CODE,ES:CODE
  1559.         
  1560.         MOV     SI,var1_value
  1561.         MOV     BL,1
  1562.         CALL    scan4char
  1563.  
  1564.         PUSH    SI
  1565.         PUSH    SI
  1566.         MOV     BYTE PTR [SI],0
  1567.         CMP     BYTE PTR [SI+1],0
  1568.         JE      noCmdLine
  1569.         POP     SI
  1570.         POP     SI
  1571.  
  1572.         MOV     BL,0
  1573.         CALL    scan4char
  1574.  
  1575.         PUSH    SI
  1576.         PUSH    SI
  1577.  
  1578.         MOV     BL,4
  1579.         MOV     DL,0
  1580.         CALL    scan4char
  1581.  
  1582. noCmdLine:      MOV     DI,dest_var_val
  1583.         POP     DX
  1584.  
  1585.         MOV     AX,SI
  1586.         SUB     AX,DX
  1587.         XOR     CH,CH
  1588.         MOV     CL,AL
  1589.         INC     AL
  1590.         MOV     AH,020H
  1591.         STOSW
  1592.  
  1593.         POP     SI
  1594.         REP     MOVSB
  1595.  
  1596.         MOV     AL,0DH
  1597.         STOSB
  1598.  
  1599.         MOV     AX,[local_environment]
  1600.         MOV     ES,AX
  1601.  
  1602.         MOV     WORD PTR [execParmBlock],ES
  1603.  
  1604.         MOV     AX,dest_var_val ;Command tail
  1605.         MOV     WORD PTR [execParmBlock+2],AX
  1606.         MOV     WORD PTR [execParmBlock+4],DS
  1607.  
  1608.         MOV     AX,005CH        ;FCB1 is at PSP:005Ch
  1609.         MOV     WORD PTR [execParmBlock+6],AX
  1610.         MOV     WORD PTR [execParmBlock+8],ES
  1611.  
  1612.         MOV     AX,006CH        ;FCB2 is at PSP:006Ch
  1613.         MOV     WORD PTR [execParmBlock+10],AX
  1614.         MOV     WORD PTR [execParmBlock+12],ES
  1615.  
  1616.         PUSH    DS              ;Point ES:BX to parmblk
  1617.         POP     ES
  1618.         MOV     BX,OFFSET execParmBlock
  1619.         MOV     DX,var1_value   ;Point DS:DX to ASCIIZ filespec
  1620.         MOV     [saved_ss],SS   ;Save our stack pointer
  1621.         MOV     [saved_sp],SP
  1622.         MOV     AX,4B00H        ;Execute child process
  1623.         INT     21H
  1624.  
  1625.         MOV     SS,CS:[saved_ss]        
  1626.         MOV     SP,CS:[saved_sp]
  1627.  
  1628.         JC      errlvl_error
  1629.  
  1630.         MOV     AH,4DH
  1631.         INT     21H
  1632.  
  1633.         XOR     AH,AH
  1634.         XOR     DX,DX
  1635.         MOV     DI,dest_var_val
  1636.         CALL    hex2asc
  1637. errlvl_exit:    CLC
  1638.         RET
  1639. errlvl_error:   CALL    parse_doserr
  1640.         STC
  1641.         RET
  1642. errlvl_file     ENDP
  1643.  
  1644. ;=============================================================================
  1645. ; System Functions
  1646. ;=============================================================================
  1647. ;-----------------------------------------------------------------------------
  1648. ; VER SYS returns the DOS version number
  1649. ;-----------------------------------------------------------------------------
  1650. ver_sys         proc    near
  1651.         assume  cs:code,ds:code,es:code
  1652.         mov     ax,dos_version          ;Get DOS verison
  1653.         mov     di,dest_var_val
  1654.         call    printver                ;Print version
  1655.         clc
  1656.         ret
  1657. ver_sys         endp
  1658.  
  1659. ;-----------------------------------------------------------------------------
  1660. ; ASK SYS prints a string then returns the user response.
  1661. ;-----------------------------------------------------------------------------
  1662. ask_sys         proc    near
  1663.         assume  cs:code,ds:code,es:code
  1664.         mov     al,quiet_flag           ;Save state of quiet flag
  1665.         push    ax
  1666.         mov     quiet_flag,0            ;Clear quiet flag for this
  1667.         mov     si,var1_value           ;  function.
  1668.         cmp     byte ptr [si],0
  1669.         je      ask_1
  1670.         call    print_strcr             ;Print prompt string
  1671. ask_1:
  1672.         mov     bx,databuff_ptr
  1673.         mov     byte ptr [bx],127       ;Set buffer size
  1674.         mov     dx,bx
  1675.         mov     ah,0ah                  ;Buffered keyboard input
  1676.         int     21h
  1677.  
  1678.         mov     si,offset endmsg
  1679.         call    print_str               ;Insert a CR-LF
  1680.  
  1681.         xor     cx,cx                   ;Append zero to string.
  1682.         inc     bx
  1683.         mov     cl,[bx]
  1684.         inc     bx
  1685.         mov     si,bx
  1686.         add     bx,cx
  1687.         mov     byte ptr [bx],0
  1688.         inc     cx
  1689.         mov     di,dest_var_val         ;Move string to result buff
  1690.         rep     movsb
  1691.         xor     al,al
  1692.         stosb
  1693.  
  1694.         clc
  1695.         pop     ax
  1696.         mov     quiet_flag,al
  1697.         ret
  1698. ask_sys         endp
  1699.  
  1700. ;-----------------------------------------------------------------------------
  1701. ; ASK2 SYS prints a string then returns the user response.
  1702. ;-----------------------------------------------------------------------------
  1703. ask2_sys        proc    near
  1704.         assume  cs:code,ds:code,es:code
  1705.         mov     al,quiet_flag           ;Save state of quiet flag
  1706.         push    ax
  1707.         mov     quiet_flag,0            ;Clear quiet flag 
  1708.         xor     bx,bx                   ;Clear password flag
  1709.         mov     cx,VAR_SIZE - 1
  1710.         cmp     num_params,1
  1711.         jb      ask2_3
  1712.         je      ask2_2
  1713.  
  1714.         mov     si,var3_value           ;Chk for password flag
  1715.         call    asc2hex
  1716.         cmp     ax,2
  1717.         ja      ask2_1
  1718.         mov     bx,ax                   ;Copy password flag 
  1719. ask2_1:
  1720.         mov     si,var2_value           ;Get max num of chars
  1721.         call    asc2hex
  1722.         mov     cx,ax
  1723.         cmp     cx,VAR_SIZE - 1
  1724.         mov     si,offset errmsg14      ;Number too large
  1725.         ja      ask2_error
  1726. ask2_2:
  1727.         mov     si,var1_value
  1728.         call    print_str               ;Print prompt string
  1729. ask2_3:
  1730.         mov     di,dest_var_val
  1731.         call    read_console
  1732.  
  1733.         mov     si,offset endmsg
  1734.         call    print_str               ;Insert a CR-LF
  1735.  
  1736.         clc
  1737. ask2_exit:
  1738.         pop     ax
  1739.         mov     quiet_flag,al
  1740.         ret
  1741. ask2_error:
  1742.         stc
  1743.         jmp     short ask2_exit
  1744. ask2_sys        endp
  1745.  
  1746. ;-----------------------------------------------------------------------------
  1747. ; RC SYS returns the return code from the prev process
  1748. ;-----------------------------------------------------------------------------
  1749. rc_sys          proc    near
  1750.         assume  cs:code,ds:code,es:code
  1751.         mov     ah,4dh                  ;Get return code
  1752.         int     21h
  1753.         xor     ah,ah
  1754.         xor     dx,dx
  1755.         mov     di,dest_var_val
  1756.         call    hex2asc
  1757.         clc
  1758.         ret
  1759. rc_sys          endp
  1760.  
  1761. ;-----------------------------------------------------------------------------
  1762. ; ENVFREE SYS returns the number of bytes free in the environment.
  1763. ;-----------------------------------------------------------------------------
  1764. envfree_sys     proc    near
  1765.         assume  cs:code,ds:code,es:code
  1766.         push    es
  1767.  
  1768.         mov     ax,masterenv_seg
  1769.         cmp     use_mastenv,0
  1770.         jne     envfree_0
  1771.         mov     ax,localenv_seg
  1772. envfree_0:
  1773.         push    ax
  1774.         dec     ax
  1775.         mov     es,ax
  1776.         mov     dx,es:[3]               ;Get size of env segment
  1777.         mov     cl,4                    ;Convert paragraphs to bytes
  1778.         shl     dx,cl
  1779.         pop     es
  1780.  
  1781.         mov     cx,dx
  1782.         xor     ax,ax
  1783.         xor     di,di
  1784. envfree_1:
  1785.         repne   scasb                   ;Loop through the environment
  1786.         cmp     byte ptr es:[di],al     ;  until the end of the
  1787.         loopne  envfree_1               ;  env strings is found.
  1788.         jcxz    envfree_2
  1789.         mov     ax,dx
  1790.         sub     ax,di
  1791.         dec     ax                      ;Sub byte for extra zero
  1792. envfree_2:
  1793.         xor     dx,dx
  1794.         pop     es
  1795.         mov     di,dest_var_val
  1796.         call    hex2asc
  1797.         clc
  1798. envfree_exit:
  1799.         ret
  1800. envfree_sys     endp
  1801.  
  1802. ;-----------------------------------------------------------------------------
  1803. ; ENVSIZE SYS returns the size of the environment.
  1804. ;-----------------------------------------------------------------------------
  1805. envsize_sys     proc    near
  1806.         assume  cs:code,ds:code,es:code
  1807.         push    es
  1808.  
  1809.         mov     ax,masterenv_seg
  1810.         cmp     use_mastenv,0
  1811.         jne     envsize_1
  1812.         mov     ax,localenv_seg
  1813. envsize_1:
  1814.         push    ax
  1815.         dec     ax
  1816.         mov     es,ax
  1817.         mov     ax,es:[3]               ;Get size of env segment
  1818.         mov     cl,4                    ;Convert paragraphs to bytes
  1819.         shl     ax,cl
  1820.         pop     es
  1821.  
  1822.         xor     dx,dx
  1823.         pop     es
  1824.         mov     di,dest_var_val
  1825.         call    hex2asc
  1826.         clc
  1827.         ret
  1828. envsize_sys     endp
  1829.  
  1830. ;-----------------------------------------------------------------------------
  1831. ; MASTERVAR SYS returns the value from a variable in the master environment.
  1832. ;-----------------------------------------------------------------------------
  1833. mastervar_sys   proc    near
  1834.         assume  cs:code,ds:code,es:code
  1835.         push    ds
  1836.         push    es
  1837.  
  1838.         mov     ax,masterenv_seg
  1839.         mov     di,var1_value           ;Point to env var name
  1840.         call    getenvvar               ;Get ptr to env var value
  1841.         jc      mastervar_exit          ;CF = 1, var not found.
  1842.  
  1843.         mov     di,cs:dest_var_val      ;Copy var value to dest string
  1844.         call    copy_string
  1845.         clc
  1846. mastervar_exit:
  1847.         pop     ds
  1848.         pop     es
  1849.         ret
  1850. mastervar_sys   endp
  1851.  
  1852. ;-----------------------------------------------------------------------------
  1853. ; LOCALVAR SYS returns the value from a variable in the local environment.
  1854. ;-----------------------------------------------------------------------------
  1855. localvar_sys    proc    near
  1856.         assume  cs:code,ds:code,es:code
  1857.         push    ds
  1858.         push    es
  1859.  
  1860.         mov     ax,localenv_seg
  1861.         mov     di,var1_value           ;Point to env var name
  1862.         call    getenvvar               ;Get ptr to env var value
  1863.         jc      localvar_exit           ;CF = 1, var not found.
  1864.  
  1865.         mov     di,cs:dest_var_val      ;Copy var value to dest string
  1866.         call    copy_string
  1867.         clc
  1868. localvar_exit:
  1869.         pop     ds
  1870.         pop     es
  1871.         ret
  1872. localvar_sys    endp
  1873.  
  1874. ;-----------------------------------------------------------------------
  1875. ; INWIN SYS returns 1 if Windows currently running.
  1876. ;-----------------------------------------------------------------------
  1877. inwin_sys       proc    near
  1878.         assume  cs:code,ds:code,es:code
  1879.         mov     ax,1600h                ;See if enhanced mode Win
  1880.         int     2fh
  1881.         or      al,al
  1882.         jne     inwin_1
  1883.  
  1884.         mov     ax,4680h                ;See if std or real Win
  1885.         int     2fh
  1886.         or      al,al
  1887.         mov     al,0
  1888.         jne     inwin_2
  1889. inwin_1:
  1890.         mov     al,1                    ;Indicate Windows active
  1891. inwin_2:
  1892.         xor     ah,ah
  1893.         xor     dx,dx
  1894.         mov     di,dest_var_val
  1895.         call    hex2asc                 ;Convert result to ASCII
  1896.         clc
  1897.         ret
  1898. inwin_sys       endp
  1899.  
  1900. ;-----------------------------------------------------------------------
  1901. ; INT2FCHECK Calls Interupt 2F (Multiplex) to determine if a program is 
  1902. ;            loaded.
  1903. ;-----------------------------------------------------------------------
  1904. int2fcheck_sys  proc    near
  1905.         assume  cs:code,ds:code,es:code
  1906.         xor     ax,ax
  1907.         cmp     dos_version,300h        ;Don't call 2F if DOS 2.x
  1908.         jb      int2fcheck_3
  1909.  
  1910.         mov     si,var1_value           ;Point to 1st parameter
  1911.         call    caps_string
  1912.  
  1913.         mov     di,offset int2fname_tbl ;See if an alias is used in
  1914.         call    findstr                 ;  place of a number.
  1915.         jc      int2fcheck_1
  1916.  
  1917.         mov     al,[bx+offset int2falias_tbl]
  1918.         jmp     short int2fcheck_2
  1919. int2fcheck_1:
  1920.         mov     si,var1_value           ;Convert 1st parameter to hex
  1921.         call    asc2hex
  1922.         mov     si,offset errmsg14      ;Number too large
  1923.         or      dx,dx
  1924.         jne     int2fcheck_error        ;Make sure the number is 
  1925.         or      ah,ah                   ;  less than 256
  1926.         jne     int2fcheck_error
  1927. int2fcheck_2:
  1928.         xor     ah,ah
  1929.         xchg    ah,al                   ;Device number in AH 0 in AL
  1930.         cmp     ah,13h                  ;Don't call for device 13
  1931.         je      int2fcheck_3
  1932.         push    si
  1933.         push    bp
  1934.         pushf
  1935.         mov     saved_sp,sp
  1936.         int     2fh
  1937.         cli
  1938.         mov     bx,cs                   ;Assume nothing after blind
  1939.         mov     ds,bx                   ;  Int 2F call.  Restore stack
  1940.         mov     es,bx                   ;  and other registers.
  1941.         mov     ss,bx
  1942.         mov     sp,saved_sp
  1943.         sti
  1944.         popf
  1945.         pop     bp
  1946.         pop     si
  1947. int2fcheck_3:
  1948.         xor     ah,ah
  1949.         xor     dx,dx
  1950.         mov     di,dest_var_val
  1951.         call    hex2asc                 ;Convert result to ASCII
  1952.         clc
  1953. int2fcheck_exit:
  1954.         ret
  1955. int2fcheck_error:
  1956.         stc
  1957.         jmp     short int2fcheck_exit
  1958. int2fcheck_sys  endp
  1959.  
  1960. ;-----------------------------------------------------------------------
  1961. ; FILES SYS  Returns the number of files that can be opened
  1962. ;-----------------------------------------------------------------------
  1963. files_sys       proc    near
  1964.         assume  cs:code,ds:code,es:code
  1965.         push    es
  1966.         mov     ah,52h                  ;Get list of lists
  1967.         int     21h
  1968.         les     bx,es:[bx+4]            ;Get ptr to Sys File Table
  1969.         xor     ax,ax                   ;Clear count
  1970. files_1:
  1971.         mov     cx,es                   ;If ptr -1, no more 
  1972.         cmp     bx,-1                   ;  entries.
  1973.         je      files_3
  1974. files_2:
  1975.         add     ax,es:[bx+4]            ;Add num of files in tbl
  1976.         les     bx,es:[bx]              ;Get ptr to next file tbl
  1977.         jmp     short files_1
  1978. files_3:
  1979.         pop     es
  1980.         xor     dx,dx
  1981.         mov     di,dest_var_val
  1982.         call    hex2asc                 ;Convert result to ASCII
  1983.         clc
  1984.         ret
  1985. files_sys       endp
  1986.  
  1987. ;-----------------------------------------------------------------------
  1988. ; LASTDRIVE SYS  Returns the last drive letter allowed by system
  1989. ;-----------------------------------------------------------------------
  1990. lastdrive_sys   proc    near
  1991.         push    es
  1992.         mov     ah,52h                  ;Get list of lists
  1993.         int     21h
  1994.         mov     si,10h                  ;Assume 2.x offset
  1995.         cmp     dos_version,300h
  1996.         jb      lastdrive_1
  1997.         mov     si,1bh                  ;Assume 3.0 offset
  1998.         cmp     dos_version,310h
  1999.         jb      lastdrive_1
  2000.         mov     si,1bh                  ;Assume 3.1,2,3 offset
  2001.         cmp     dos_version,400h
  2002.         jb      lastdrive_1
  2003.         mov     si,21h                  ;Assume 4.x, 5.x offset
  2004. lastdrive_1:
  2005.         mov     al,es:[bx+si]           ;Get lastdrive value
  2006.         add     ax,'@'                  ;Convert to letter
  2007.         pop     es
  2008.         mov     di,dest_var_val
  2009.         mov     ah,':'
  2010.         stosw
  2011.         xor     al,al                   ;Append terminating 0
  2012.         stosb
  2013.         clc
  2014.         ret
  2015. lastdrive_sys   endp
  2016.  
  2017. ;------------------------------------------------------------------------
  2018. ; TRUEVER SYS returns the real DOS version number. DOS 5 or later
  2019. ;------------------------------------------------------------------------
  2020. truever_sys     proc    near
  2021.         assume  cs:code,ds:code,es:code
  2022.         mov     ax,dos_version          ;Get std DOS version
  2023.         cmp     ax,500h
  2024.         jb      truever_1
  2025.         mov     ax,3306h                ;Get real DOS version
  2026.         int     21h
  2027.         mov     ax,bx
  2028.         xchg    al,ah
  2029. truever_1:
  2030.         mov     di,dest_var_val
  2031.         call    printver                ;Print version
  2032.         clc
  2033. truever_exit:
  2034.         ret
  2035. truever_sys     endp
  2036.  
  2037. ;------------------------------------------------------------------------
  2038. ; CODEPAGE SYS returns the active code page
  2039. ;------------------------------------------------------------------------
  2040. codepage_sys    proc    near
  2041.         assume  cs:code,ds:code,es:code
  2042.         mov     ax,31eh
  2043.         cmp     ax,dos_version          ;See if DOS 3.3 
  2044.         ja      codepage_error
  2045.         mov     ax,6601h                ;Get global code page
  2046.         int     21h
  2047.         mov     ax,bx                   ;Get code page
  2048.         xor     dx,dx
  2049.         mov     di,dest_var_val
  2050.         call    hex2asc                 ;Print code page
  2051.         clc
  2052. codepage_exit:
  2053.         ret
  2054. codepage_error:
  2055.         call    seterr0msg              ;Error, not DOS 3.3
  2056.         jmp     short codepage_exit
  2057. codepage_sys    endp
  2058.  
  2059. ;------------------------------------------------------------------------
  2060. ; COUNTRY SYS returns the active code page
  2061. ;------------------------------------------------------------------------
  2062. country_tbl     db      0,2,7,9,11,13,15,16,17,22
  2063. country_sys     proc    near
  2064.         assume  cs:code,ds:code,es:code
  2065.         mov     ax,3800h                ;Get country info
  2066.         mov     dx,databuff_ptr         ;Point to data buffer
  2067.         int     21h
  2068.         xor     ah,ah
  2069.         cmp     al,-1
  2070.         jne     countrysys_1
  2071.         mov     ax,bx                   ;Get country code
  2072. countrysys_1:
  2073.         cmp     num_params,0
  2074.         je      countrysys_4
  2075.         mov     si,var1_value
  2076.         call    asc2hex
  2077.         mov     si,databuff_ptr
  2078.         cmp     ax,9
  2079.         ja      countrysys_error
  2080. countrysys_2:
  2081.         mov     cl,al
  2082.         mov     bx,offset country_tbl
  2083.         xlat    
  2084.         add     si,ax
  2085.         mov     ax,[si]                 ;Get word
  2086.         or      cl,cl
  2087.         je      countrysys_4
  2088.         xor     ah,ah                   ;Other than 0, byte
  2089.         
  2090.         cmp     cl,5                    ;1,2,3,4,9 are
  2091.         jbe     countrysys_3            ;  ASCIIZ strings
  2092.         cmp     cl,9
  2093.         je      countrysys_3
  2094.         jmp     short countrysys_4
  2095. countrysys_3:
  2096.         mov     di,dest_var_val         ;Copy string
  2097.         call    copy_string
  2098.         jmp     short countrysys_exit
  2099. countrysys_4:
  2100.         xor     dx,dx
  2101.         mov     di,dest_var_val
  2102.         call    hex2asc                 ;Print code page
  2103. countrysys_exit:
  2104.         clc
  2105. countrysys_exit1:
  2106.         ret
  2107. countrysys_error:
  2108.         stc
  2109.         mov     si,offset errmsg14      ;Number too large
  2110.         jmp     short countrysys_exit1
  2111. country_sys     endp
  2112.  
  2113. ;------------------------------------------------------------------------
  2114. ; BIOSDATE SYS returns the date of the ROM BIOS
  2115. ;------------------------------------------------------------------------
  2116. biosdate_sys    proc    near
  2117.         assume  cs:code,ds:code,es:code
  2118.         push    ds
  2119.         mov     si,0f000h               ;ROM segment
  2120.         mov     ds,si
  2121.         mov     si,0fff5h               ;Offset of date
  2122.         mov     di,cs:dest_var_val
  2123.         mov     cx,4                    ;Copy 8 bytes
  2124.         rep     movsw
  2125.         pop     ds
  2126.         xor     al,al                   ;Add terminating 0
  2127.         stosb
  2128.         clc
  2129.         ret
  2130. biosdate_sys    endp
  2131.  
  2132. ;------------------------------------------------------------------------
  2133. ; GETKEY SYS Waits for a key and returns the ASCII code and scan code 
  2134. ;------------------------------------------------------------------------
  2135. getkey_sys      proc    near
  2136.         assume  cs:code,ds:code,es:code
  2137.         call    getkey
  2138.         mov     di,dest_var_val
  2139.         push    ax
  2140.         xor     ah,ah
  2141.         xor     dx,dx
  2142.         call    hex2asc
  2143.         mov     byte ptr [di-1],' '     ;Replace term 0 with space
  2144.         pop     ax
  2145.         xor     al,al
  2146.         xchg    al,ah
  2147.         call    hex2asc
  2148.         clc
  2149.         ret
  2150. getkey_sys      endp
  2151.  
  2152. ;------------------------------------------------------------------------
  2153. ; LOCALENV SYS Returns the segment of the local env
  2154. ;------------------------------------------------------------------------
  2155. localenv_sys    proc    near
  2156.         assume  cs:code,ds:code,es:code
  2157.         mov     ax,localenv_seg
  2158.         xor     dx,dx
  2159.         mov     di,dest_var_val
  2160.         call    hex2asc
  2161.         clc
  2162.         ret
  2163. localenv_sys    endp
  2164.  
  2165. ;------------------------------------------------------------------------
  2166. ; MASTERENV SYS Returns the segment of the master env
  2167. ;------------------------------------------------------------------------
  2168. masterenv_sys   proc    near
  2169.         assume  cs:code,ds:code,es:code
  2170.         mov     ax,masterenv_seg
  2171.         xor     dx,dx
  2172.         mov     di,dest_var_val
  2173.         call    hex2asc
  2174.         clc
  2175.         ret
  2176. masterenv_sys   endp
  2177.  
  2178. ;========================================================================
  2179. ; Number Functions
  2180. ;========================================================================
  2181. ;------------------------------------------------------------------------
  2182. ; ADD NUM returns the sum of a series of numbers
  2183. ;------------------------------------------------------------------------
  2184. add_num         proc    near
  2185.         assume  cs:code,ds:code,es:code
  2186.         mov     bx,offset addnum_callback
  2187.         call    process_nums            ;Process vars
  2188.         mov     si,offset errmsg12      ;Overflow message
  2189.         ret
  2190. addnum_callback:
  2191.         add     si,ax                   ;Add number to running
  2192.         adc     di,dx                   ;  sum.
  2193.         ret
  2194. add_num         endp
  2195.  
  2196. ;------------------------------------------------------------------------
  2197. ; SUB NUM returns the difference of two numbers
  2198. ;------------------------------------------------------------------------
  2199. sub_num         proc    near
  2200.         assume  cs:code,ds:code,es:code
  2201.         mov     bx,offset subnum_callback
  2202.         call    process_nums            ;Process vars
  2203.         mov     si,offset errmsg13      ;Underflow message
  2204.         ret
  2205. subnum_callback:
  2206.         sub     si,ax                   ;Add number to running
  2207.         sbb     di,dx                   ;  sum.
  2208.         ret
  2209. sub_num         endp
  2210.  
  2211. ;------------------------------------------------------------------------
  2212. ; MUL NUM returns the product of two numbers
  2213. ;------------------------------------------------------------------------
  2214. mul_num         proc    near
  2215.         assume  cs:code,ds:code,es:code
  2216.         mov     bx,offset mulnum_callback
  2217.         call    process_nums            ;Process vars
  2218.         mov     si,offset errmsg13      ;Overflow message
  2219. mulnum_exit:
  2220.         ret
  2221. mul_num_error:
  2222.         stc
  2223.         mov     si,offset errmsg10      ;Multiply overflow
  2224.         stc
  2225.         jmp     short mulnum_exit
  2226. mulnum_callback:
  2227.         push    bx
  2228.         push    cx
  2229.         push    dx
  2230.         push    bp
  2231.         mov     cx,dx                   ;Copy numbers
  2232.         mov     bx,ax
  2233.         mul     cx                      ;32 bit multiply.
  2234.         jc      mulcb_exit              ;Param 1 in DI,SI
  2235.         mov     bp,ax                   ;Param 2 in CX,BX
  2236.         mov     ax,di
  2237.         mul     cx                      ;              DI   SI
  2238.         or      ax,dx                   ;              CX   BX
  2239.         jnz     mulcb_exit              ; ---------------------
  2240.         mov     ax,di                   ;             (BX * SI)
  2241.         mul     bx                      ;        (BX * DI)
  2242.         jc      mulcb_exit              ;        (CX * SI)
  2243.         add     bp,ax                   ; + (CX * DI)
  2244.         mov     ax,si                   ; ---------------------
  2245.         mul     bx                      ;              DX   AX
  2246.         add     dx,bp
  2247.         mov     si,ax
  2248.         mov     di,dx
  2249. mulcb_exit:
  2250.         pop     bp
  2251.         pop     dx
  2252.         pop     cx
  2253.         pop     bx
  2254.         ret
  2255. mul_num         endp
  2256.  
  2257. ;------------------------------------------------------------------------
  2258. ; DIV NUM returns the quotient of two numbers
  2259. ;------------------------------------------------------------------------
  2260. div_num         proc    near
  2261.         assume  cs:code,ds:code,es:code
  2262.         call    conv2num                ;Convert first two parms to
  2263.         jc      div_num_exit            ;  32 bit numbers.
  2264.         push    cx
  2265.         or      cx,bx                   ;Prevent divide by zero
  2266.         pop     cx
  2267.         jz      div_num_error
  2268. div_num_1:
  2269.         or      cx,cx                   ;Divide both numbers by 2
  2270.         je      div_num_2               ;  until high word of
  2271.         shr     dx,1                    ;  divisor (CX) is zero.
  2272.         rcr     ax,1
  2273.  
  2274.         shr     cx,1
  2275.         rcr     bx,1
  2276.         jmp     short div_num_1
  2277. div_num_2:
  2278.         push    ax                      ;Save low word
  2279.         mov     ax,dx
  2280.         xor     dx,dx
  2281.         div     bx                      ;Divide high word
  2282.         mov     cx,ax                   ;Save high quotent
  2283.         pop     ax
  2284.         div     bx                      ;Divide low word
  2285.         mov     dx,cx
  2286.  
  2287.         mov     di,dest_var_val
  2288.         call    hex2asc                 ;Convert result to ASCII
  2289. div_num_exit:
  2290.         ret
  2291. div_num_error:
  2292.         mov     si,offset errmsg11
  2293.         stc
  2294.         jmp     short div_num_exit
  2295. div_num         endp
  2296.  
  2297. ;------------------------------------------------------------------------
  2298. ; AND NUM returns the logical AND of two numbers
  2299. ;------------------------------------------------------------------------
  2300. and_num         proc    near
  2301.         assume  cs:code,ds:code,es:code
  2302.         mov     bx,offset andnum_callback
  2303.         call    process_nums            ;Process vars
  2304.         mov     si,offset errmsg14      ;Number too large
  2305.         ret
  2306. andnum_callback:
  2307.         and     si,ax                   ;AND number 
  2308.         and     di,dx                   ;  
  2309.         ret
  2310. and_num         endp
  2311.  
  2312. ;------------------------------------------------------------------------
  2313. ; OR NUM returns the logical OR of two numbers
  2314. ;------------------------------------------------------------------------
  2315. or_num          proc    near
  2316.         assume  cs:code,ds:code,es:code
  2317.         mov     bx,offset ornum_callback
  2318.         call    process_nums            ;Process vars
  2319.         mov     si,offset errmsg14      ;Number too large
  2320.         ret
  2321. ornum_callback:
  2322.         or      si,ax                   ;OR number 
  2323.         or      di,dx                   ;  
  2324.         ret
  2325. or_num          endp
  2326.  
  2327. ;------------------------------------------------------------------------
  2328. ; XOR NUM returns the logical exclusive OR of two numbers
  2329. ;------------------------------------------------------------------------
  2330. xor_num         proc    near
  2331.         assume  cs:code,ds:code,es:code
  2332.         call    conv2num                ;Convert first two parms to
  2333.         jc      xor_num_exit            ;  32 bit numbers.  Carry
  2334.         xor     ax,bx                   ;  set, overflow.
  2335.         xor     dx,cx
  2336.         mov     di,dest_var_val
  2337.         call    hex2asc                 ;Convert result to ASCII
  2338. xor_num_exit:
  2339.         ret
  2340. xor_num         endp
  2341.     
  2342. ;------------------------------------------------------------------------
  2343. ; NOT NUM returns the inverse of a number
  2344. ;------------------------------------------------------------------------
  2345. not_num         proc    near
  2346.         assume  cs:code,ds:code,es:code
  2347.         mov     si,var1_value           ;Convert 1st parameter to hex
  2348.         call    asc2hex
  2349.         mov     si,offset errmsg14      ;Number too large
  2350.         jc      not_num_exit            ;If error, exit
  2351.         not     ax
  2352.         not     dx
  2353.         mov     di,dest_var_val
  2354.         call    hex2asc                 ;Convert result to ASCII
  2355. not_num_exit:
  2356.         ret
  2357. not_num         endp
  2358.  
  2359. ;------------------------------------------------------------------------
  2360. ; CONVERT NUM converts a number to the base specified by 2nd param
  2361. ;------------------------------------------------------------------------
  2362. convert_num     proc    near
  2363.         assume  cs:code,ds:code,es:code
  2364.         call    conv2num                ;Convert first two parms
  2365.         or      cx,cx
  2366.         jne     convertnum_error
  2367.         cmp     bx,16
  2368.         ja      convertnum_error
  2369.         cmp     bl,1
  2370.         jbe     convertnum_error
  2371.         mov     number_base,bx
  2372.         mov     di,dest_var_val
  2373.         call    hex2asc                 ;Convert result to ASCII
  2374. convertnum_exit:
  2375.         ret
  2376. convertnum_error:
  2377.         mov     si,offset errmsg14      ;Number too large
  2378.         stc
  2379.         jmp     short convertnum_exit
  2380. convert_num     endp
  2381.  
  2382. ;------------------------------------------------------------------------
  2383. ; GT NUM checks to see if parameter 1 is greater than parameter 2
  2384. ;------------------------------------------------------------------------
  2385. gt_num          PROC    NEAR
  2386.                 ASSUME  CS:CODE,DS:CODE,ES:CODE
  2387.  
  2388.                 XOR     SI,SI
  2389. gt_alt:         PUSH    SI
  2390.                 MOV     SI,var1_value           ;Convert 1st parameter to hex
  2391.                 CALL    asc2hex
  2392.                 MOV     BX,AX
  2393.                 MOV     CX,DX
  2394.                 MOV     SI,var2_value           ;Convert 2nd parameter to hex
  2395.                 CALL    asc2hex
  2396.                 POP     SI
  2397.                 MOV     DI,dest_var_val
  2398.                 CMP     CX,DX
  2399.                 JB      gtnum_false
  2400.                 JA      gtnum_true
  2401.                 CMP     BX,AX
  2402.                 JB      gtnum_false
  2403.                 JE      gtnum_equal
  2404. gtnum_true:     MOV     AX,1
  2405.                 JMP     SHORT gtnum_exit
  2406. gtnum_equal:    CMP     SI,1
  2407.                 JE      gtnum_true
  2408. gtnum_false:    XOR     AX,AX
  2409. gtnum_exit:     XOR     DX,DX
  2410.                 CALL    hex2asc
  2411.                 RET
  2412. gt_num          ENDP
  2413.  
  2414. ;------------------------------------------------------------------------
  2415. ; LT NUM checks to see if parameter 1 is lesser than parameter 2
  2416. ;------------------------------------------------------------------------
  2417. lt_num          PROC    NEAR
  2418.                 ASSUME  CS:CODE,DS:CODE,ES:CODE
  2419.  
  2420.                 XOR     SI,SI
  2421. lt_alt:         PUSH    SI
  2422.                 MOV     SI,var1_value           ;Convert 1st parameter to hex
  2423.                 CALL    asc2hex
  2424.                 MOV     BX,AX
  2425.                 MOV     CX,DX
  2426.                 MOV     SI,var2_value           ;Convert 2nd parameter to hex
  2427.                 CALL    asc2hex
  2428.                 POP     SI
  2429.                 MOV     DI,dest_var_val
  2430.                 CMP     CX,DX
  2431.                 JA      ltnum_false
  2432.                 JB      ltnum_true
  2433.                 CMP     BX,AX
  2434.                 JA      ltnum_false
  2435.                 JE      ltnum_equal
  2436. ltnum_true:     MOV     AX,1
  2437.                 JMP     SHORT ltnum_exit
  2438. ltnum_equal:    CMP     SI,1
  2439.                 JE      ltnum_true
  2440. ltnum_false:    XOR     AX,AX
  2441. ltnum_exit:     XOR     DX,DX
  2442.                 CALL    hex2asc
  2443.                 RET
  2444. lt_num          ENDP
  2445.  
  2446. ;------------------------------------------------------------------------
  2447. ; GE NUM checks to see if parameter 1 is greater than parameter 2
  2448. ;------------------------------------------------------------------------
  2449. ge_num          PROC    NEAR
  2450.                 ASSUME  CS:CODE,DS:CODE,ES:CODE
  2451.  
  2452.                 MOV     SI,1
  2453.                 JMP     SHORT gt_alt
  2454. ge_num          ENDP
  2455. ;------------------------------------------------------------------------
  2456. ; LE NUM checks to see if parameter 1 is greater than parameter 2
  2457. ;------------------------------------------------------------------------
  2458. le_num          PROC    NEAR
  2459.                 ASSUME  CS:CODE,DS:CODE,ES:CODE
  2460.  
  2461.                 MOV     SI,1
  2462.                 JMP     SHORT lt_alt
  2463. le_num          ENDP
  2464.  
  2465. ;========================================================================
  2466. ; Programming Functions
  2467. ;========================================================================
  2468. ;------------------------------------------------------------------------
  2469. ; PEEK PROG Returns byte(s) from memory
  2470. ;------------------------------------------------------------------------
  2471. peek_prog       proc    near
  2472.         assume  cs:code,ds:code,es:code
  2473.         push    bp
  2474.         call    conv2num                ;Convert first two parms to
  2475.         jc      peek_prog_exit          ;  32 bit numbers.  
  2476.         mov     si,offset errmsg14
  2477.         or      dx,cx                   ;Check to see that neither
  2478.         jne     peek_prog_err1          ;  number > 64K
  2479.         mov     cx,1                    ;Assume 1 byte peek
  2480.         mov     bp,0                    ;Assume byte size peek
  2481.         mov     di,dest_var_val         ;Pt to output buff
  2482.         mov     si,ax                   ;Save seg value
  2483.  
  2484.         cmp     num_params,3            ;If 3rd param, it is the
  2485.         jb      peek_prog_1             ;  number of bytes to
  2486.         push    ax                      ;  return
  2487.         push    bx
  2488.         push    si
  2489.         mov     si,var3_value
  2490.         call    asc2hex
  2491.         mov     cx,ax
  2492.         pop     si
  2493.         pop     bx
  2494.         pop     ax
  2495.         cmp     num_params,4            ;If 4th param, it signals
  2496.         jb      peek_prog_1             ;  word size peek
  2497.         mov     bp,1
  2498.         shr     cx,1
  2499. peek_prog_1:
  2500.         and     cx,003fh                ;Allow only 64 bytes out
  2501.         jne     peek_prog_2
  2502.         mov     cx,1
  2503. peek_prog_2:
  2504.         push    es
  2505.         mov     es,si
  2506.         mov     ax,es:[bx]
  2507.         pop     es
  2508.  
  2509.         or      bp,bp                   ;If word size, print
  2510.         je      peek_prog_3             ;  high byte first.
  2511.         push    ax
  2512.         xor     al,al
  2513.         xchg    ah,al
  2514.         xor     dx,dx
  2515.         call    lead_zero
  2516.         call    hex2asc                 ;Convert result to ASCII
  2517.         inc     bx
  2518.         dec     di
  2519.         pop     ax
  2520. peek_prog_3:
  2521.         xor     ah,ah
  2522.         xor     dx,dx
  2523.         call    lead_zero
  2524.         call    hex2asc                 ;Convert result to ASCII
  2525.         inc     bx
  2526.         mov     byte ptr [di-1],' '     ;Replace term 0 with space
  2527.         loop    peek_prog_1
  2528.  
  2529.         mov     byte ptr [di-1],0       ;Restore term 0
  2530. peek_prog_exit:
  2531.         pop     bp
  2532.         ret
  2533. peek_prog_err1:
  2534.         stc
  2535.         jmp     short peek_prog_exit
  2536. peek_prog       endp
  2537.  
  2538. ;------------------------------------------------------------------------
  2539. ; POKE PROG Writes a string of bytes to memory
  2540. ;------------------------------------------------------------------------
  2541. poke_prog       proc    near
  2542.         assume  cs:code,ds:code,es:code
  2543.         call    conv2num                ;Convert first two parms to
  2544.         jc      poke_prog_exit          ;  32 bit numbers.  
  2545.         mov     si,offset errmsg14      ;Number too large
  2546.         or      dx,cx                   ;Check to see that neither
  2547.         jne     poke_prog_error         ;  number > 64K
  2548.  
  2549.         mov     si,offset errmsg18      ;Not enough parameters
  2550.         mov     cx,num_params
  2551.         sub     cx,2
  2552.         jbe     poke_prog_error
  2553.         mov     si,offset var3_value
  2554.         push    es
  2555.         mov     es,ax                   ;Load segment
  2556.         mov     di,bx                   ;Load offset
  2557.         cli             
  2558. poke_prog_1:
  2559.         push    si
  2560.         mov     si,[si]                 ;Get ptr to next var    
  2561.         call    asc2hex
  2562.         pop     si
  2563.         jnc     poke_prog_3
  2564. poke_prog_2:
  2565.         sti
  2566.         pop     es
  2567.         mov     si,offset errmsg14      ;Number too large
  2568.         stc     
  2569.         jmp     poke_prog_exit
  2570. poke_prog_3:
  2571.         or      dx,dx                   ;Check to see if poke
  2572.         jne     poke_prog_2             ;  val > 256
  2573.         or      ah,ah
  2574.         jne     poke_prog_2
  2575.  
  2576.         stosb
  2577.         inc     si                      ;Move ptr to next var
  2578.         inc     si
  2579.         loop    poke_prog_1
  2580.         pop     es
  2581.  
  2582.         mov     di,dest_var_val         ;Zero return value
  2583.         mov     byte ptr [di],0
  2584.         clc
  2585. poke_prog_exit:
  2586.         ret
  2587. poke_prog_error:
  2588.         stc
  2589.         jmp     short poke_prog_exit
  2590. poke_prog       endp
  2591.  
  2592. ;------------------------------------------------------------------------
  2593. ; IN PROG Returns a byte from an IO port.
  2594. ;------------------------------------------------------------------------
  2595. in_prog         proc    near
  2596.         assume  cs:code,ds:code,es:code
  2597.         mov     si,var1_value           ;Convert 1st param to hex
  2598.         call    asc2hex
  2599.         mov     si,offset errmsg14      ;Number too large
  2600.         jc      in_prog_exit            ;If error, exit
  2601.  
  2602.         or      dx,dx                   ;Make sure number not too
  2603.         jne     in_prog_error           ;  big.
  2604.  
  2605.         mov     dx,ax
  2606.         in      al,dx
  2607.  
  2608.         xor     ah,ah
  2609.         xor     dx,dx
  2610.         mov     di,dest_var_val
  2611.         call    hex2asc                 ;Convert result to ASCII
  2612. in_prog_exit:
  2613.         ret
  2614. in_prog_error:
  2615.         stc
  2616.         jmp     short in_prog_exit
  2617. in_prog         endp
  2618.  
  2619. ;------------------------------------------------------------------------
  2620. ; OUT PROG Outputs a byte to an IO port.
  2621. ;------------------------------------------------------------------------
  2622. out_prog        proc    near
  2623.         assume  cs:code,ds:code,es:code
  2624.         call    conv2num                ;Convert first two parms to
  2625.         jc      out_prog_exit           ;  32 bit numbers.  
  2626.         mov     si,offset errmsg14      ;Number too large
  2627.         or      dx,dx                   ;Check to see that neither
  2628.         jne     out_prog_error          ;  number > 64K
  2629.         or      cx,cx
  2630.         jne     poke_prog_error
  2631.         or      bh,bh
  2632.         jne     poke_prog_error
  2633.         
  2634.         mov     dl,bl
  2635.         xchg    ax,dx
  2636.         out     dx,al
  2637.         mov     di,dest_var_val         ;Zero output
  2638.         mov     byte ptr [di],0
  2639. out_prog_exit:
  2640.         ret
  2641. out_prog_error:
  2642.         stc
  2643.         jmp     short out_prog_exit
  2644. out_prog        endp
  2645. ;------------------------------------------------------------------------
  2646. ; INTERRUPT PROG Performs an system interrupt
  2647. ; NOTE:  This routine contains self modifying code!!!
  2648. ;------------------------------------------------------------------------
  2649. interrupt_prog  proc    near
  2650.         assume  cs:code,ds:code,es:code
  2651.         push    bp
  2652.         mov     si,var1_value           ;Convert 1st param to hex
  2653.         call    asc2hex
  2654.         jnc     intprog_0
  2655. intprog_error:
  2656.         mov     si,offset errmsg14      ;Number too large
  2657.         stc
  2658.         jmp     short intprog_error
  2659. intprog_0:
  2660.         or      dl,dh                   ;Make sure number not too
  2661.         or      dl,ah                   ;  big.
  2662.         jne     intprog_error
  2663.         mov     si,offset intprog_opcode
  2664.  
  2665.         mov     [si+1],al               ;Set interrupt number
  2666.  
  2667.         mov     bp,offset var1_value    ;Get ptr to array
  2668.         mov     cx,9
  2669. intprog_1:
  2670.         inc     bp
  2671.         inc     bp
  2672.         mov     si,[bp]                 ;Get ptr to next param
  2673.         call    asc2hex                 ;Convert to hex
  2674.         or      dx,dx                   ;Limit test
  2675.         jne     intprog_error
  2676.         mov     [bp],ax                 ;Save hex value
  2677.         loop    intprog_1               
  2678.  
  2679.         std                             ;Set direction down!
  2680.         mov     si,bp                   ;copy ptr to array
  2681.         lodsw
  2682.         mov     es,ax
  2683.         assume  es:nothing
  2684.         lodsw
  2685.         push    ax                      ;Save DS for later
  2686.         lodsw
  2687.         mov     bp,ax
  2688.         lodsw
  2689.         push    ax                      ;Save SI for later
  2690.         lodsw
  2691.         mov     di,ax
  2692.         lodsw
  2693.         mov     dx,ax
  2694.         lodsw
  2695.         mov     cx,ax
  2696.         lodsw
  2697.         mov     bx,ax
  2698.         lodsw
  2699.         pop     si
  2700.         pop     ds
  2701. intprog_2:
  2702.         cld                             ;For neatness
  2703.         assume  ds:nothing
  2704.         mov     cs:saved_ssint,ss
  2705.         mov     cs:saved_spint,sp               
  2706. intprog_opcode:
  2707.         int     2fh                     ;Perform interrupt
  2708.  
  2709.         cli
  2710.         mov     ss,cs:saved_ssint       ;Restore stack
  2711.         mov     sp,cs:saved_spint
  2712.         sti
  2713.         pushf
  2714.         cld                             ;Set dir flag UP
  2715.         push    es
  2716.         push    di
  2717.         push    cs
  2718.         pop     es
  2719.         assume  es:code
  2720.         mov     di,offset var1_value
  2721.         stosw                           ;Save AX
  2722.         mov     ax,bx
  2723.         stosw
  2724.         mov     ax,cx
  2725.         stosw
  2726.         mov     ax,dx
  2727.         stosw
  2728.         pop     ax                      ;Get returned DI
  2729.         stosw
  2730.         mov     ax,si
  2731.         stosw
  2732.         mov     ax,bp
  2733.         stosw
  2734.         mov     ax,ds
  2735.         stosw
  2736.         pop     ax                      ;Get returned ES
  2737.         stosw
  2738.         pop     ax                      ;Get returned flags             
  2739.         stosw
  2740.  
  2741.         push    cs                      ;Reset DS = CS
  2742.         pop     ds
  2743.         assume  ds:code
  2744.         mov     si,offset var1_value
  2745.         mov     di,dest_var_val         ;Zero output
  2746.         mov     cx,10
  2747. intprog_3:
  2748.         lodsw                           ;Get reg value
  2749.         xor     dx,dx
  2750.         call    hex2asc                 ;Convert number
  2751.         mov     byte ptr [di-1],' '
  2752.         loop    intprog_3
  2753.         mov     byte ptr [di-1],0       ;Restore last 0
  2754.         clc
  2755. intprog_exit:
  2756.         pop     bp
  2757.         ret
  2758. interrupt_prog  endp
  2759.  
  2760. ;------------------------------------------------------------------------
  2761. ; SCAN PROG Returns byte(s) from memory
  2762. ;------------------------------------------------------------------------
  2763. scan_prog       proc    near
  2764.         assume  cs:code,ds:code,es:code
  2765.         push    bp
  2766.         mov     bp,offset var3_value    ;Get ptr to scan bytes
  2767.         mov     di,databuff_ptr         ;Use file data buff
  2768.         mov     cx,num_params
  2769.         sub     cx,2
  2770.         jbe     scan_prog_error
  2771.         mov     bx,cx                   ;Save byte count
  2772. scan_prog_0:
  2773.         mov     si,[bp]                 ;Get ptr to variable
  2774.         inc     bp                      ;Point BP to next var
  2775.         inc     bp
  2776.         call    asc2hex                 ;Convert ASCII num to
  2777.         stosb                           ;  hex num and store.
  2778.         or      dx,dx
  2779.         jne     scan_prog_err1
  2780.         or      ah,ah
  2781.         jne     scan_prog_err1
  2782.         loop    scan_prog_0
  2783.         xor     al,al                   ;Term string
  2784.         stosb
  2785.         mov     bp,bx                   ;Save scan str length
  2786.  
  2787.         call    conv2num                ;Convert first two parms to
  2788.         jc      scan_prog_exit          ;  32 bit numbers.  
  2789.         mov     si,offset errmsg14
  2790.         or      dx,cx                   ;Check to see that neither
  2791.         jne     scan_prog_err1          ;  number > 64K
  2792.         push    es
  2793.         mov     es,ax                   ;Get segment
  2794.         mov     dx,databuff_ptr         ;DX pts to scan string
  2795.         mov     cx,bx                   ;Scan remaining segment
  2796.         neg     cx
  2797. scan_prog_2:
  2798.         push    cx
  2799.         mov     di,bx                   ;Get mem offset 
  2800.         mov     si,dx                   ;Get scan str offset
  2801.         mov     cx,bp                   ;Get scan str length
  2802.         rep     cmpsb
  2803.         pop     cx
  2804.         je      scan_prog_3
  2805.         inc     bx
  2806.         loop    scan_prog_2
  2807.         pop     es
  2808.         mov     si,offset errmsg20      ;String not found
  2809.         jmp     short scan_prog_error
  2810. scan_prog_3:
  2811.         pop     es
  2812.         xor     dx,dx
  2813.         mov     di,dest_var_val
  2814.         call    hex2asc
  2815.         mov     byte ptr [di-1],' '     ;Replace 0 with space
  2816.         mov     ax,bx
  2817.         call    hex2asc
  2818.         clc
  2819. scan_prog_exit:
  2820.         pop     bp
  2821.         ret
  2822. scan_prog_err1:
  2823.         mov     si,offset errmsg14      ;Number too large
  2824. scan_prog_error:
  2825.         stc
  2826.         jmp     short scan_prog_exit
  2827. scan_prog       endp
  2828.  
  2829. ;========================================================================
  2830. ; Time and Date Functions
  2831. ;========================================================================
  2832. ;------------------------------------------------------------------------
  2833. ; DAY TIME Returns the name of the current day
  2834. ;------------------------------------------------------------------------
  2835. day_time        proc    near
  2836.         assume  cs:code,ds:code,es:code
  2837.         cmp     num_params,1
  2838.         jae     day_time_1
  2839.         mov     ah,2ah                  ;Get system day
  2840.         int     21h
  2841.         xor     ah,ah
  2842.         jmp     short day_time_2
  2843. day_time_1:
  2844.         mov     si,var1_value           ;Convert 1st parameter to hex
  2845.         call    asc2hex
  2846.         mov     si,offset errmsg14      ;Number too large
  2847.         jc      day_time_exit           ;If error, exit
  2848.         or      dx,dx
  2849.         jne     day_time_error
  2850.         or      ax,ax
  2851.         je      day_time_error
  2852.         cmp     ax,7
  2853.         ja      day_time_error
  2854.         dec     ax
  2855. day_time_2:
  2856.         mov     bx,ax
  2857.         mov     di,offset day_list
  2858.         call    get_string
  2859.         
  2860.         mov     si,cs:dest_var_val      
  2861.         xchg    si,di
  2862.         call    copy_string
  2863.         clc
  2864. day_time_exit:
  2865.         ret
  2866. day_time_error:
  2867.         stc
  2868.         jmp     short day_time_exit
  2869. day_time        endp
  2870.  
  2871. ;------------------------------------------------------------------------
  2872. ; MONTH TIME Returns the name of the current month
  2873. ;------------------------------------------------------------------------
  2874. month_time      proc    near
  2875.         assume  cs:code,ds:code,es:code
  2876.         cmp     num_params,1
  2877.         jae     month_time_1
  2878.         mov     ah,2ah                  ;Get system date
  2879.         int     21h
  2880.         mov     bl,dh
  2881.         xor     bh,bh
  2882.         jmp     short month_time_2
  2883. month_time_1:
  2884.         mov     si,var1_value           ;Convert 1st parameter to hex
  2885.         call    asc2hex
  2886.         mov     si,offset errmsg14      ;Number too large
  2887.         jc      month_time_exit           ;If error, exit
  2888.         or      dx,dx
  2889.         jne     month_time_error
  2890.         or      ax,ax
  2891.         je      month_time_error
  2892.         cmp     ax,12
  2893.         ja      month_time_error
  2894.         mov     bx,ax
  2895. month_time_2:
  2896.         dec     bx
  2897.         mov     di,offset month_list
  2898.         call    get_string
  2899.         
  2900.         mov     si,cs:dest_var_val      
  2901.         xchg    si,di
  2902.         call    copy_string
  2903.         clc
  2904. month_time_exit:
  2905.         ret
  2906. month_time_error:
  2907.         stc
  2908.         jmp     short month_time_exit
  2909. month_time      endp
  2910.  
  2911. ;------------------------------------------------------------------------
  2912. ; DOW TIME Returns the day of the week (1=Sunday)
  2913. ;------------------------------------------------------------------------
  2914. dow_time        proc    near
  2915.         assume  cs:code,ds:code,es:code
  2916.         mov     ah,2ah                  ;Get system date
  2917.         int     21h
  2918.         inc     al
  2919.         
  2920.         xor     ah,ah
  2921.         xor     dx,dx
  2922.         mov     di,dest_var_val
  2923.         call    hex2asc
  2924.         clc
  2925.         ret
  2926. dow_time        endp
  2927.  
  2928. ;-----------------------------------------------------------------------
  2929. ; DATE TIME Returns the current date.  The date is returned either 
  2930. ;           as Month xx, 199x or as mm-dd-yyyy depending on params.
  2931. ;-----------------------------------------------------------------------
  2932. date_time       proc    near
  2933.         assume  cs:code,ds:code,es:code
  2934.  
  2935.         xor     ax,ax                   ;Clear style flag
  2936.         cmp     num_params,1
  2937.         jb      date_time_1
  2938.         mov     si,var1_value           ;Convert 1st parameter to hex
  2939.         call    asc2hex
  2940.         jc      date_time_error
  2941.         mov     si,offset errmsg14      ;Number too large
  2942.         or      dx,dx
  2943.         jne     date_time_error
  2944.         cmp     al,1
  2945.         ja      date_time_error
  2946. date_time_1:
  2947.         push    ax
  2948.  
  2949.         mov     ah,2ah                  ;Get system date
  2950.         int     21h
  2951.         xor     ah,ah
  2952.         pop     bx                      ;Get back style param
  2953.  
  2954.         cmp     bl,1
  2955.         je      date_time_2
  2956.  
  2957.         push    cx                      ;Save year
  2958.         push    dx                      ;Save day of the month
  2959.         mov     bl,dh                   ;Copy month
  2960.         dec     bx
  2961.         mov     di,offset month_list
  2962.         call    get_string
  2963.         
  2964.         mov     si,dest_var_val 
  2965.         xchg    si,di
  2966.         call    copy_string
  2967.         mov     byte ptr [di-1],' '     ;Change term 0 to space
  2968.         pop     ax                      ;Get day
  2969.         xor     ah,ah
  2970.         xor     dx,dx
  2971.         call    hex2asc                 ;Convert day to ASCII
  2972.         mov     word ptr [di-1],' ,'    ;Change term 0 to , space
  2973.         inc     di
  2974.         pop     ax                      ;Get year
  2975.         xor     dx,dx
  2976.         call    hex2asc                 ;Convert year to ASCII
  2977.         jmp     short date_time_exit
  2978. date_time_2:
  2979.         mov     di,dest_var_val
  2980.         call    print_date              ;Print in mm-dd-yyyy fmt
  2981. date_time_exit:
  2982.         clc
  2983. date_time_exit1:
  2984.         ret
  2985. date_time_error:
  2986.         stc
  2987.         jmp     short date_time_exit1
  2988. date_time       endp
  2989.  
  2990. ;-----------------------------------------------------------------------
  2991. ; TIME TIME Returns the current time.  
  2992. ;-----------------------------------------------------------------------
  2993. time_time       proc    near
  2994.         assume  cs:code,ds:code,es:code
  2995.  
  2996.         mov     ah,2ch                  ;Get system date
  2997.         int     21h
  2998.  
  2999.         mov     di,dest_var_val 
  3000.         call    print_time              ;Print in hh:mm:ss fmt
  3001. time_time_exit:
  3002.         clc
  3003. time_time_exit1:
  3004.         ret
  3005. time_time_error:
  3006.         stc
  3007.         jmp     short time_time_exit1
  3008. time_time       endp
  3009.  
  3010. ;=======================================================================
  3011. ; Memory functions
  3012. ;=======================================================================
  3013. ;-----------------------------------------------------------------------
  3014. ; TOTALMEM MEM  Returns the size of the largest blk of free conv mem
  3015. ;-----------------------------------------------------------------------
  3016. totalmem_mem    proc    near
  3017.         assume  cs:code,ds:code,es:code
  3018.         int     12h                     ;Get conv mem size
  3019. totalmem_2:
  3020.         mov     cx,1024                 ;Convert Kbytes
  3021.         mul     cx                      ;  to bytes
  3022.         mov     di,dest_var_val 
  3023.         call    hex2asc
  3024.         clc
  3025.         ret
  3026. totalmem_mem    endp
  3027.  
  3028. ;-----------------------------------------------------------------------
  3029. ; FREEMEM MEM  Returns the size of the largest blk of free conv mem
  3030. ;-----------------------------------------------------------------------
  3031. freemem_mem     proc    near
  3032.         assume  cs:code,ds:code,es:code
  3033.         cmp     installed,0
  3034.         je      freemem_1
  3035.         mov     ah,48h
  3036.         mov     bx,-1                   ;Ask for all mem
  3037.         int     21h
  3038.         mov     ax,bx
  3039.         jmp     short freemem_2
  3040. freemem_1:
  3041.         mov     ax,ds:[2]               ;Get end of mem ptr
  3042.         mov     bx,cs
  3043.         sub     ax,bx
  3044. freemem_2:
  3045.         mov     cx,16                   ;Convert paragraphs
  3046.         mul     cx                      ;  to bytes
  3047.         mov     di,dest_var_val 
  3048.         call    hex2asc
  3049.         clc
  3050.         ret
  3051. freemem_mem     endp
  3052.  
  3053. ;-----------------------------------------------------------------------
  3054. ; FREEEXT MEM  Returns the size of extended memory
  3055. ;-----------------------------------------------------------------------
  3056. freeext_mem     proc    near
  3057.         assume  cs:code,ds:code,es:code
  3058.         cmp     xms_version,0           ;See if mem driver
  3059.         je      freeext_1
  3060.  
  3061.         mov     ah,8
  3062.         call    ds:[xms_serv]           ;Call driver
  3063.         jmp     short freeext_2
  3064. freeext_1:
  3065.         mov     ah,88h                  ;Get ext mem size
  3066.         int     15h                     ;   BIOS call
  3067.         jnc     freeext_2
  3068.         xor     ax,ax
  3069. freeext_2:
  3070.         mov     cx,1024                 ;Convert 1K to bytes
  3071.         mul     cx                      
  3072.         mov     di,dest_var_val 
  3073.         call    hex2asc
  3074.         clc
  3075. freeext_exit:
  3076.         ret
  3077. freeext_mem     endp
  3078.  
  3079. ;-----------------------------------------------------------------------
  3080. ; TOTALEXT MEM  Returns the size of extended memory
  3081. ;-----------------------------------------------------------------------
  3082. totalext_mem    proc    near
  3083.         assume  cs:code,ds:code,es:code
  3084.         cmp     xms_version,0           ;See if mem driver
  3085.         je      totalext_1
  3086.  
  3087.         mov     ah,8
  3088.         call    ds:[xms_serv]           ;Call driver
  3089.         mov     ax,dx
  3090.         jmp     short totalext_2
  3091. totalext_1:
  3092.         mov     ah,88h                  ;Get ext mem size
  3093.         int     15h                     ;   BIOS call
  3094.         jnc     totalext_2
  3095.         xor     ax,ax
  3096. totalext_2:
  3097.         mov     cx,1024                 ;Convert 1K to bytes
  3098.         mul     cx                      
  3099.         mov     di,dest_var_val 
  3100.         call    hex2asc
  3101.         clc
  3102. totalext_exit:
  3103.         ret
  3104. totalext_mem    endp
  3105.  
  3106. ;-----------------------------------------------------------------------
  3107. ; EXTVER MEM  Returns the version of the extended memory driver
  3108. ; Check version again, since some driver change version reporting
  3109. ; depending on the system environment.
  3110. ;-----------------------------------------------------------------------
  3111. extver_mem      proc    near
  3112.         assume  cs:code,ds:code,es:code
  3113.         mov     ax,xms_version          ;See if mem driver
  3114.         or      ax,ax
  3115.         je      extver_1
  3116.         
  3117.         xor     ax,ax
  3118.         call    ds:[xms_serv]           ;Get version number
  3119.         mov     bx,ax                   ;Version num returned
  3120.         shr     al,1                    ;  as BCD.  Convert
  3121.         shr     al,1                    ;  to std DOS format
  3122.         shr     al,1                    ;  of maj in AH and
  3123.         shr     al,1                    ;  minor in AL
  3124.         mov     ah,10
  3125.         mul     ah
  3126.         and     bl,0fh
  3127.         add     al,bl
  3128.         mov     ah,bh
  3129. extver_1:
  3130.         mov     di,dest_var_val 
  3131.         call    printver
  3132.         clc
  3133. extver_exit:
  3134.         ret
  3135. extver_mem      endp
  3136.  
  3137. ;-----------------------------------------------------------------------
  3138. ; TOTALEMS MEM  Returns the size of Expanded memory
  3139. ;-----------------------------------------------------------------------
  3140. totalems_mem    proc    near
  3141.         assume  cs:code,ds:code,es:code
  3142.         xor     ax,ax
  3143.         or      ax,ems_version
  3144.         je      totalems_1
  3145.         mov     ah,42h                  ;Get EMS Mem amounts
  3146.         int     67h                     ;Call driver
  3147.         mov     ax,dx
  3148.         mov     cx,16384                ;Convert 16K pages 
  3149.         mul     cx                      ;  to bytes
  3150. totalems_1:
  3151.         mov     di,dest_var_val 
  3152.         call    hex2asc
  3153.         clc
  3154. totalems_exit:
  3155.         ret
  3156. totalems_mem    endp
  3157.  
  3158. ;-----------------------------------------------------------------------
  3159. ; FREEEMS MEM  Returns the amount of free Expanded memory
  3160. ;-----------------------------------------------------------------------
  3161. freeems_mem     proc    near
  3162.         assume  cs:code,ds:code,es:code
  3163.         xor     ax,ax
  3164.         or      ax,ems_version
  3165.         je      freeems_1
  3166.         mov     ah,42h                  ;Get EMS Mem amounts
  3167.         int     67h                     ;Call driver
  3168.         mov     ax,bx
  3169.         mov     cx,16384                ;Convert 16K pages 
  3170.         mul     cx                      ;  to bytes
  3171. freeems_1:
  3172.         mov     di,dest_var_val 
  3173.         call    hex2asc
  3174.         clc
  3175. freeems_exit:
  3176.         ret
  3177. freeems_mem     endp
  3178.  
  3179. ;-----------------------------------------------------------------------
  3180. ; EMSVER MEM  Returns the version of the extended memory driver
  3181. ; Check version again, since some driver change version reporting
  3182. ; depending on the system environment.
  3183. ;-----------------------------------------------------------------------
  3184. emsver_mem      proc    near
  3185.         assume  cs:code,ds:code,es:code
  3186.         mov     ax,ems_version          ;See if mem driver
  3187.         or      ax,ax
  3188.         je      emsver_1
  3189.         mov     ah,46h                  ;Get version
  3190.         int     67h
  3191.         or      ah,ah
  3192.         je      emsver_0
  3193.         xor     ax,ax
  3194. emsver_0:
  3195.         mov     bl,al                   ;Convert ver number
  3196.         shl     ax,1
  3197.         shl     ax,1
  3198.         shl     ax,1
  3199.         shl     ax,1
  3200.         mov     al,bl
  3201.         and     ax,0f0fh
  3202. emsver_1:
  3203.         mov     di,dest_var_val 
  3204.         call    printver
  3205.         clc
  3206. emsver_exit:
  3207.         ret
  3208. emsver_mem      endp
  3209.  
  3210. ;-----------------------------------------------------------------------
  3211. ; FREEUMB MEM  Returns the size of the largest free upper memory block 
  3212. ;-----------------------------------------------------------------------
  3213. freeumb_mem     proc    near
  3214.         assume  cs:code,ds:code,es:code
  3215.         cmp     dos_version,500h
  3216.         jae     freeumb_0
  3217.  
  3218.         cmp     xms_version,0
  3219.         mov     cx,0
  3220.         je      freeumb_3
  3221.         mov     dx,-1
  3222.         mov     ah,10h                  ;Request umb from drvr
  3223.         call    ds:[xms_serv]
  3224.         mov     cx,dx                   ;Save largest available
  3225.         jmp     short freeumb_3
  3226. freeumb_0:
  3227.         mov     ax,5800h                ;Get allocation strat
  3228.         int     21h
  3229.         push    ax                      ;Save strategy
  3230.         mov     ax,5802h                ;Get UMB link state
  3231.         int     21h
  3232.         push    ax                      ;Save link state
  3233.         mov     ax,5803h                ;Link UMBs
  3234.         mov     bx,1
  3235.         int     21h
  3236.         jnc     freeumb_1
  3237.         call    check4xms               ;See for ext mem drvr
  3238.         mov     cx,0
  3239.         jc      freeumb_2
  3240.         mov     dx,-1
  3241.         mov     ah,10h                  ;Request umb from drvr
  3242.         call    ds:[xms_serv]
  3243.         mov     cx,dx                   ;Save largest available
  3244.         jmp     short freeumb_2
  3245. freeumb_1:
  3246.         mov     ax,5801h                ;Set mem alloc strat
  3247.         mov     bx,41h                  ;Best fit high only
  3248.         int     21h
  3249.         mov     ah,48h                  ;Alloc mem
  3250.         mov     bx,-1
  3251.         int     21h
  3252.         mov     cx,bx                   ;Save largest block
  3253. freeumb_2:
  3254.         pop     bx                      ;Get UMB link state
  3255.         mov     ax,5803h
  3256.         int     21h
  3257.         pop     bx                      ;Get mem alloc strat
  3258.         mov     ax,5801h
  3259.         int     21h
  3260. freeumb_3:
  3261.         mov     ax,cx
  3262.         mov     cx,16
  3263.         mul     cx
  3264.         mov     di,dest_var_val 
  3265.         call    hex2asc
  3266.         clc
  3267. freeumb_exit:                   
  3268.         ret
  3269. freeumb_error:
  3270.         call    seterr0msg              ;Error, not DOS 5.0
  3271.         jmp     short freeumb_exit
  3272. freeumb_mem     endp
  3273.  
  3274. ;=======================================================================
  3275. ; Program Support Functions
  3276. ;=======================================================================
  3277. ;-----------------------------------------------------------------------
  3278. ; HELP STRINGS  Help function for the program ###
  3279. ;-----------------------------------------------------------------------
  3280. help_tag1       db      "Function: ",0
  3281. help_tag2       db      " - Returns ",0
  3282. help_tag3       db      13,10,"Syntax:   STRINGS [dest var =] ",0
  3283. help_tag4       db      "  ",0
  3284. help_tag5       db      "This is a list of the available commands"
  3285. help_tag7       db      ".",13,10,0
  3286. help_tag6       db      13,10,"For help on a specific command type:  "
  3287.         db      "STRINGS HELP Command",0
  3288. help_error      db      "Command Help not available once installed",0
  3289.  
  3290. help_strings    proc    near
  3291.         assume  cs:code,ds:code,es:code
  3292.         push    bp
  3293.  
  3294.         mov     si,offset program       ;Print copyright msg
  3295.         call    print_strcr
  3296.  
  3297.         mov     si,cmd_value            ;Point to command buffer
  3298.         cmp     help_flag,0
  3299.         jne     help_1
  3300.         mov     si,var1_value
  3301. help_1:
  3302.         mov     bp,si
  3303.         call    caps_string             ;Search cmd table for
  3304.         inc     cx                      ;  function. If not
  3305.         mov     di,offset command_table ;  found, print general
  3306.         call    findstr                 ;  help message.
  3307.         jc      help_3
  3308.  
  3309.         cmp     installed,0             ;If installed, cmd help
  3310.         je      help_2                  ;  not loaded.
  3311.         mov     si,offset help_error
  3312.         jmp     short help_7
  3313. help_2:
  3314.         mov     si,offset help_tag1     ;Print lead in.
  3315.         call    print_str
  3316.  
  3317.         mov     si,bp
  3318.         call    print_str               ;Print function name
  3319.  
  3320.         mov     si,offset help_tag2     ;Print sep
  3321.         call    print_str
  3322.  
  3323.         shl     bx,1                    ;Convert index into 
  3324.         shl     bx,1                    ;  offset into help tbl
  3325.  
  3326.         mov     si,[bx+offset help_tbl] ;Print description
  3327.         call    print_str
  3328.         mov     si,offset help_tag7     ;Print usage for fun
  3329.         call    print_str
  3330.  
  3331.         mov     si,offset help_tag3     ;Print usage for fun
  3332.         call    print_str
  3333.  
  3334.         mov     si,bp                   ;Get ptr to command
  3335.         call    print_str               ;Print function name
  3336.  
  3337.         mov     si,offset help_tag4     ;Print sep
  3338.         call    print_str
  3339.  
  3340.         mov     si,[bx + offset help_tbl + 2]
  3341.         call    print_strcr             ;Print syntax
  3342.         jmp     short help_exit
  3343. help_3:
  3344.         mov     si,offset help_tag5     ;Print global help msg
  3345.         call    print_strcr
  3346.  
  3347.         mov     si,offset command_table ;Print every cmd in 
  3348.         xor     bl,bl                   ;  the command table.
  3349. help_4:
  3350.         mov     di,dest_var_val
  3351.         mov     cx,6
  3352. help_5:
  3353.         push    cx
  3354.         call    copy_string             ;Copy command
  3355.         dec     di
  3356.         mov     al,' '                  ;Print a cmd every
  3357.         neg     cx                      ;  15 columns.  Fill
  3358.         add     cx,13                   ;  in the space with
  3359.         rep     stosb                   ;  blanks.
  3360.         pop     cx
  3361.         mov     bl,[si]                 ;See if end of list
  3362.         or      bl,bl
  3363.         je      help_6
  3364.         loop    help_5
  3365. help_6:
  3366.         xor     al,al
  3367.         stosb
  3368.         push    si
  3369.         mov     si,dest_var_val
  3370.         call    print_strcr
  3371.         pop     si
  3372.         or      bl,bl
  3373.         jne     help_4
  3374.  
  3375.         cmp     installed,0             ;If installed, don't tell
  3376.         jne     help_exit               ;  user about cmd help.
  3377.  
  3378.         mov     si,offset help_tag6     ;Print global help msg
  3379. help_7:
  3380.         call    print_strcr
  3381. help_exit:
  3382.         mov     di,dest_var_val
  3383.         xor     al,al
  3384.         stosb
  3385.         clc
  3386.         pop     bp
  3387.         ret
  3388. help_strings    endp
  3389.  
  3390. ;-----------------------------------------------------------------------
  3391. ; STRINGSVER  Returns the Strings version
  3392. ;-----------------------------------------------------------------------
  3393. ver_strings     proc    near
  3394.         mov     si,offset version
  3395.         lodsb
  3396.         mov     ah,[si+1]
  3397.         mov     di,dest_var_val
  3398.         stosw
  3399.         mov     ax,0030h                ;Add ASCII 0 and term
  3400.         stosw
  3401.         clc             
  3402.         ret
  3403. ver_strings     endp
  3404.  
  3405. ;-----------------------------------------------------------------------
  3406. ; STRINGSINST  Checks to see if Strings installed as TSR
  3407. ;-----------------------------------------------------------------------
  3408. inst_strings    proc    near
  3409.         xor     ax,ax
  3410.         mov     dx,ax
  3411.         mov     al,installed
  3412.         mov     di,dest_var_val
  3413.         call    hex2asc
  3414.         clc             
  3415.         ret
  3416. inst_strings    endp
  3417.  
  3418. ;=======================================================================
  3419. ; Support Procedures
  3420. ;=======================================================================
  3421. ;-----------------------------------------------------------------------
  3422. ;Read Console  Gets input from the user
  3423. ; Entry:   CX - Max number of characters to read
  3424. ;          BL - Set to prevent echo of input
  3425. ;          DI - Ptr to output buffer
  3426. ;-----------------------------------------------------------------------
  3427. ;readcon_keys    dw      27,4b00h,8,32                                  ;2.0 CW
  3428. ;READCON_KEYCNT  equ     4                                              ;2.0 CW
  3429. readcon_keys    DW      27,4B00H,8,0                                    ;2.4 CW
  3430. READCON_KEYCNT  EQU     4                                               ;2.4 CW
  3431. ;readcon_jmptbl  dw      offset readcon_echo                            ;2.0 CW
  3432. ;                dw      offset readcon_bs                              ;2.0 CW
  3433. ;                dw      offset readcon_bs                              ;2.0 CW
  3434. ;                dw      offset readcon_esc                             ;2.0 CW
  3435. readcon_jmptbl  DW      OFFSET readcon_echo                             ;2.4 CW
  3436.                 DW      OFFSET readcon_bs                               ;2.4 CW
  3437.                 DW      OFFSET readcon_bs                               ;2.4 CW
  3438.                 DW      OFFSET readcon_esc                              ;2.4 CW
  3439.  
  3440. readcon_scur    equ     word ptr [bp-2]
  3441. readcon_sptr    equ     word ptr [bp-4]
  3442. readcon_cpos    equ     word ptr [bp-6]
  3443. readcon_scnt    equ     word ptr [bp-8]
  3444. readcon_pswf    equ     word ptr [bp-10]
  3445.         
  3446. read_console    proc    near
  3447.         push    bp
  3448.         mov     bp,sp
  3449.         sub     sp,10
  3450.         push    cx
  3451.         mov     ah,0fh                  ;Get display mode/page
  3452.         int     10h
  3453.         mov     ah,3                    ;Get init cursor pos
  3454.         int     10h
  3455.         pop     cx
  3456.         mov     readcon_scur,dx         ;Save init cursor pos
  3457.         mov     readcon_cpos,0          ;Position inside str
  3458.         mov     readcon_sptr,di         ;Ptr to output buff 
  3459.         mov     readcon_scnt,cx         ;Num chars to read 
  3460.         mov     readcon_pswf,bx         ;Password flag
  3461. readcon_0:
  3462.         call    prog_idle               ;Indicate idle
  3463.         mov     ah,6
  3464.         mov     dl,-1                   ;Get keyboard input
  3465.         int     21h
  3466.         jz      readcon_0               ;No key, wait
  3467.         xor     ah,ah
  3468.         or      al,al                   ;If extended key get
  3469.         jne     readcon_1               ;  another.
  3470.  
  3471.         mov     ah,6
  3472.         mov     dl,-1                   ;Get extended key
  3473.         int     21h                     ;  code.
  3474.         xor     ah,ah
  3475.         xchg    ah,al
  3476. readcon_1:
  3477. ;               cmp     al,13                   ;See if CR              ;2.0 CW
  3478. ;               je      readcon_exit                                    ;2.0 CW
  3479. ;               jcxz    readcon_3                                       ;2.0 CW
  3480.         push    cx
  3481.         push    di
  3482.         mov     di,offset readcon_keys
  3483.         mov     cx,READCON_KEYCNT
  3484.         repne   scasw
  3485.         mov     si,cx
  3486.         pop     di
  3487.         pop     cx
  3488.         je      readcon_2
  3489.  
  3490.                 cmp     al,13                   ;See if CR              ;2.2 CW
  3491.                 je      readcon_exit                                    ;2.2 CW
  3492.                 jcxz    readcon_3                                       ;2.2 CW
  3493.  
  3494.         dec     cx
  3495.         stosb                           ;Write char to buff             
  3496.         xor     si,si
  3497.         cmp     readcon_pswf,0
  3498.         je      readcon_2
  3499.         mov     al,'*'
  3500.         cmp     readcon_pswf,1
  3501.         je      readcon_2
  3502.         mov     al,' '
  3503. readcon_2:
  3504.         shl     si,1
  3505.         call    [si+offset readcon_jmptbl]
  3506.         jmp     short readcon_0
  3507. readcon_3:
  3508.         mov     al,7
  3509.         call    readcon_echo            ;Beep the speaker
  3510.         jmp     short readcon_0
  3511. readcon_exit:
  3512.         xor     al,al                   ;Terminate string
  3513.         stosb
  3514.         clc
  3515.         mov     sp,bp
  3516.         pop     bp
  3517.         ret
  3518. ;
  3519. ; Process backspace
  3520. ;
  3521. readcon_bs      proc    near
  3522.         cmp     cx,readcon_scnt         ;If at start of buff,
  3523.         je      readcon_bsexit          ;  ignore.
  3524.                 dec     di                                              ;2.2 CW
  3525.                 inc     cx                                              ;2.2 CW
  3526.         push    ax
  3527.         call    readcon_lcur            ;Backup cursor
  3528.         mov     al,' '
  3529.         call    readcon_echo            ;Print space
  3530.         pop     ax      
  3531.         call    readcon_lcur
  3532. ;               dec     di                                              ;2.0 CW
  3533. ;               inc     cx                                              ;2.0 CW
  3534. readcon_bsexit:
  3535.         stc
  3536.         ret
  3537. readcon_bs      endp
  3538. ;
  3539. ; Process left cursor
  3540. ;
  3541. readcon_lcur    proc    near
  3542.         or      cx,cx
  3543.         je      readcon_lcurexit
  3544.         mov     al,8                    ;Backspace char
  3545.         call    readcon_echo
  3546. readcon_lcurexit:
  3547.         stc
  3548.         ret
  3549. readcon_lcur    endp            
  3550. ;
  3551. ; Process escape 
  3552. ;
  3553. readcon_esc     proc    near
  3554.         cmp     cx,readcon_scnt
  3555.         je      readcon_escexit
  3556.  
  3557.         mov     ah,3                    ;Get cursor pos
  3558.         int     10h
  3559.         mov     cx,readcon_scur         ;Get init cur pos
  3560.         sub     dl,cl                   ;Compute difference
  3561.         sub     dh,ch
  3562.         push    es
  3563.         mov     ax,40h
  3564.         mov     es,ax
  3565.         mov     al,es:[4Ah]
  3566.         pop     es
  3567.         mov     ah,dh
  3568.         mul     ah
  3569.         xor     dh,dh
  3570.         add     ax,dx
  3571.         push    ax
  3572.         mov     dx,readcon_scur         ;Get initial pos
  3573.         call    setcursor
  3574.         pop     cx
  3575.         jcxz    readcon_esc2
  3576. readcon_esc1:
  3577.         mov     al,' '
  3578.         call    readcon_echo
  3579.         loop    readcon_esc1
  3580. readcon_esc2:
  3581.         mov     dx,readcon_scur         ;Get initial pos
  3582.         call    setcursor
  3583.         mov     di,readcon_sptr
  3584.         mov     cx,readcon_scnt
  3585. readcon_escexit:
  3586.         
  3587.         ret
  3588. readcon_esc     endp            
  3589. ;
  3590. ; Echo character in AL to screen.
  3591. ;
  3592. readcon_echo    proc    near
  3593.                 cmp     al,20h                                          ;2.2 CW
  3594.                 jne     readcon_echo_start                              ;2.2 CW
  3595.                 jcxz    readcon_echo_exit                               ;2.2 CW
  3596. readcon_echo_start:                                                     ;2.2 CW
  3597.         push    ax
  3598.         push    dx
  3599.         mov     dl,al                   ;Echo character
  3600.         mov     ah,2
  3601.         int     21h
  3602.         pop     dx
  3603.         pop     ax
  3604. readcon_echo_exit:                                                      ;2.2 CW
  3605.         ret                                                     
  3606. readcon_echo    endp
  3607.  
  3608. read_console    endp
  3609.  
  3610. ;-----------------------------------------------------------------------
  3611. ; SETCURSOR  Sets the position of the cursor
  3612. ; Entry: DX - New cursor position
  3613. ;        BH - Video page
  3614. ;-----------------------------------------------------------------------
  3615. setcursor       proc    near
  3616.         mov     ah,2
  3617.         int     10h
  3618. setcursor       endp
  3619.  
  3620. ;-----------------------------------------------------------------------
  3621. ; SETERR0MSG  Sets the Bad version error message to the ver in AX
  3622. ; Entry: AX - Required DOS version
  3623. ; Exit:  SI - Pointer to bad DOS ver message
  3624. ;        CF - Set 
  3625. ;-----------------------------------------------------------------------
  3626. seterr0msg      proc    near
  3627.         mov     di,offset errmsg0ver    ;Print version number
  3628.         call    printver
  3629.         mov     ax,[di-3]               ;Insert decimal pt
  3630.         mov     byte ptr [di-3],'.'     ;  so it looks nice
  3631.         mov     ah,' '
  3632.         mov     [di-2],ax
  3633.         mov     si,offset errmsg0       ;Point to start of msg
  3634.         stc                             ;Set error flag
  3635.         ret
  3636. seterr0msg      endp
  3637.  
  3638. ;-----------------------------------------------------------------------
  3639. ; PRINTVER  Prints the version number in AX to buff 
  3640. ; Entry: AX - Version number.  AH = Major ver, AL = Minor ver
  3641. ;        DI - Pointer to output buffer
  3642. ;-----------------------------------------------------------------------
  3643. printver        proc    near
  3644.         push    ax
  3645.         mov     al,100
  3646.         xchg    al,ah                   ;Copy major ver number
  3647.         mul     ah
  3648.         pop     bx
  3649.         xor     bh,bh
  3650.         add     ax,bx
  3651.         xor     dx,dx
  3652.         call    hex2asc
  3653.         ret
  3654. printver        endp
  3655.  
  3656. ;-----------------------------------------------------------------------
  3657. ; PRINT DATE  Prints a date in mm-dd-yyyy format
  3658. ; Entry: DH - Month 1 - 12
  3659. ;        DL - Day 1 - 31
  3660. ;        CX - Year
  3661. ;        DI - Ptr to output buffer
  3662. ;-----------------------------------------------------------------------
  3663. print_date      proc    near
  3664.         push    cx                      ;Save year
  3665.         push    dx                      ;Save day of the month
  3666.         mov     al,dh                   ;Copy month
  3667.         xor     ah,ah
  3668.         xor     dx,dx
  3669.         call    lead_zero               ;Add leading zero
  3670.         call    hex2asc                 ;Convert month to ASCII
  3671.         mov     byte ptr [di-1],'-'     ;Change term 0 to -
  3672.         pop     ax                      ;Get day
  3673.         xor     ah,ah                   
  3674.         call    lead_zero               ;Add leading 0
  3675.         call    hex2asc                 ;Convert to ASCII
  3676.         mov     byte ptr [di-1],'-'     ;Change term 0 to -
  3677.         pop     ax
  3678.         xor     dx,dx
  3679.         call    hex2asc                 ;Convert year to ASCII
  3680.         ret
  3681. print_date      endp
  3682.  
  3683. ;-----------------------------------------------------------------------
  3684. ; PRINT TIME  Prints the time in hh:mm:ss AM/PM format
  3685. ; Entry: CH - Hour
  3686. ;        CL - Minutes
  3687. ;        DH - Seconds
  3688. ;        DI - Ptr to output buffer
  3689. ;-----------------------------------------------------------------------
  3690. print_time      proc    near
  3691.         mov     bx,"ma"                 ;Assume AM
  3692.         cmp     ch,12
  3693.         jb      print_time_1
  3694.         sub     ch,12
  3695.         mov     bl,'p'
  3696. print_time_1:
  3697.         push    bx                      ;Save AM/PM flag
  3698.         push    dx                      ;Save seconds
  3699.         push    cx                      ;Save minutes
  3700.         mov     al,ch                   ;Copy hours
  3701.         xor     ah,ah
  3702.         xor     dx,dx
  3703.         call    lead_zero               ;Add leading zero
  3704.         call    hex2asc                 ;Convert month to ASCII
  3705.         mov     byte ptr [di-1],':'     ;Change term 0 to :
  3706.         pop     ax                      ;Get minutes
  3707.         xor     ah,ah
  3708.         xor     dx,dx
  3709.         call    lead_zero               ;Add leading 0
  3710.         call    hex2asc                 ;Convert to ASCII
  3711.         mov     byte ptr [di-1],':'     ;Change term 0 to :
  3712.         pop     ax                      ;Get seconds
  3713.         mov     al,ah
  3714.         xor     ah,ah
  3715.         xor     dx,dx
  3716.         call    lead_zero               ;Add leading 0
  3717.         call    hex2asc                 ;Convert seconds
  3718.         mov     byte ptr [di-1],' '     ;Change term 0 to space
  3719.         pop     ax                      ;Get AM/PM tag
  3720.         stosw
  3721.         xor     al,al                   ;Term string
  3722.         stosb
  3723.         clc
  3724.         ret
  3725. print_time      endp
  3726.  
  3727. ;-----------------------------------------------------------------------
  3728. ; Lead Zero - Adds a leading zero if number less than 10
  3729. ; Entry: DI - Ptr to buffer
  3730. ;        AL - Number to check
  3731. ;-----------------------------------------------------------------------
  3732. lead_zero       proc    near
  3733.         push    bx
  3734.         mov     bx,number_base
  3735.         cmp     al,bl
  3736.         jae     lead_zero_exit
  3737.         mov     byte ptr es:[di],'0'
  3738.         inc     di
  3739. lead_zero_exit:
  3740.         pop     bx
  3741.         ret
  3742. lead_zero       endp
  3743.  
  3744. ;-----------------------------------------------------------------------------
  3745. ; GETSTRING  Returns a pointer to a string in a list from depending
  3746. ;            on an input index value. 
  3747. ; Entry: ES:DI - Pointer to start of list
  3748. ;           BX - Index into list
  3749. ; Exit:     DI - Pointer to string
  3750. ;           CF - Set if index too big
  3751. ;-----------------------------------------------------------------------------
  3752. get_string      proc    near
  3753.         assume  cs:code,ds:code
  3754.         or      bx,bx                   ;CF = 0
  3755.         je      getstring_exit
  3756.         call    find_endl
  3757.         dec     bx
  3758.         cmp     byte ptr es:[di],0
  3759.         jne     get_string
  3760.         stc
  3761. getstring_exit:
  3762.         ret
  3763. get_string      endp
  3764.  
  3765. ;-----------------------------------------------------------------------
  3766. ; PROCESS NUMS  Converts each parameter to a number then calls back
  3767. ;               to a routine for specific processing.
  3768. ; Entry:      BX - Ptr to callback procedure
  3769. ;
  3770. ; Exit:     CF    - Set if number too large
  3771. ;
  3772. ; Callback: 
  3773. ;   Called with:  DX AX - Number from parameter
  3774. ;                 SI DI - Running sum/product/logical number
  3775. ;   Return:          CF - Set if processing should terminate;   
  3776. ;-----------------------------------------------------------------------
  3777. process_nums    proc    near
  3778.         push    bp
  3779.         mov     si,var1_value           ;Get ptr to variable
  3780.         call    asc2hex
  3781.         mov     si,ax                   ;Init vars
  3782.         mov     di,dx
  3783.         mov     bp,offset var2_value    ;Get ptr to var array
  3784.         mov     cx,num_params
  3785.         dec     cx
  3786.         jbe     procnum_exit
  3787. procnum_1:
  3788.         push    si
  3789.         mov     si,[bp]                 ;Get ptr to variable
  3790.         call    asc2hex
  3791.         pop     si
  3792.         jc      procnum_exit
  3793.         call    bx                      ;Call callback function
  3794.         jc      procnum_exit
  3795.         inc     bp                      ;Point BP to next var
  3796.         inc     bp
  3797.         loop    procnum_1
  3798.  
  3799.         mov     ax,si                   ;Copy number
  3800.         mov     dx,di       
  3801.         mov     di,dest_var_val
  3802.         call    hex2asc                 ;Convert result to ASCII
  3803.         clc
  3804. procnum_exit:
  3805.         pop     bp
  3806.         ret
  3807. process_nums    endp
  3808.  
  3809. ;-----------------------------------------------------------------------
  3810. ; CONV2NUM  converts the first two parameters to hex numbers.
  3811. ; Exit:    DX AX - Number from 1st parameter
  3812. ;          CX BX - Number from 2nd parameter
  3813. ;          CF    - Set if either number too large
  3814. ;          SI    - Set to error message if CF set
  3815. ;-----------------------------------------------------------------------
  3816. conv2num        proc    near
  3817.         mov     si,var2_value           ;Convert 2nd param to hex
  3818.         call    asc2hex
  3819.         jc      conv2num_error
  3820.         mov     bx,ax                   ;Copy second parameter
  3821.         mov     cx,dx
  3822.  
  3823.         mov     si,var1_value           ;Convert 1st param to hex
  3824.         call    asc2hex
  3825.         jc      conv2num_error
  3826. conv2num_exit:
  3827.         ret
  3828. conv2num_error:
  3829.         mov     si,offset errmsg14      ;Number too large
  3830.         jmp     short conv2num_exit
  3831. conv2num        endp
  3832.  
  3833. ;-----------------------------------------------------------------------
  3834. ; PARSE CMDLINE  Parse the cmd line into seperate strings for each param
  3835. ; Entry:  SI - Pointer to string to parse.
  3836. ; Exit:   CF - Set if error.
  3837. ;         SI - Points to error message if CF set.
  3838. ;-----------------------------------------------------------------------
  3839. parse_cmdline   proc    near
  3840.         xor     ax,ax
  3841.         mov     num_params,ax           ;Init flags with zeros
  3842.         mov     quiet_flag,al
  3843.         mov     use_mastenv,al
  3844.         mov     help_flag,al
  3845.         mov     number_base,10
  3846.         mov     console_out,1           
  3847.         mov     parse_char,DEF_PARSE_CHAR
  3848.  
  3849.                 mov     cx,MAX_PARAMS + 2       ;Init ptrs to zero string ;2.4 CW
  3850.         mov     di,offset dest_var_name
  3851.         mov     ax,offset entry         ;Point to zero byte
  3852.         rep     stosw
  3853.  
  3854.         mov     si,offset command_tail + 1
  3855.         cmp     byte ptr [si-1],0       ;See if cmdline = 0
  3856.         jne     parse_cmdline_1         ;If zero, report error
  3857. parse_error:
  3858.         cmp     help_flag,0
  3859.         je      parse_error1
  3860.         jmp     parse_cmdline_exit
  3861. parse_error1:
  3862.         mov     si,offset errmsg1       ;Syntax error message
  3863.         mov     al,install_flag
  3864.         or      al,remove_flag
  3865.         je      parse_error2
  3866.         mov     si,100h
  3867. parse_error2:
  3868.         stc
  3869.         jmp     parse_cmdline_exit1
  3870. parse_cmdline_0:
  3871.         inc     si
  3872. parse_cmdline_1:
  3873.         xor     cx,cx
  3874.         xor     bx,bx
  3875.         call    scan4char               ;Find 1st char
  3876.         jc      parse_error
  3877.     
  3878.         cmp     al,'/'                  ;See if cmdline switch
  3879.         jne     parse_cmdline_2
  3880.         call    parse_switch            ;Parse cmd line switch
  3881.         jnc     parse_cmdline_1
  3882.         jmp     parse_cmdline_exit1
  3883. parse_cmdline_2:
  3884.         mov     dest_var_name,si
  3885.         mov     cmd_value,si
  3886.         mov     bl,3                    ;Scan for space or =
  3887.         call    scan4char
  3888.         mov     byte ptr [si],0         ;Term 1st string
  3889.         jc      parse_cmdline_exit
  3890.         cmp     al,'='                  ;If = found, first word
  3891.         je      parse_cmdline_3         ;  was dest env var
  3892.         xor     bl,bl
  3893.         call    scan4char
  3894.         jc      parse_cmdline_exit
  3895.         cmp     al,'='
  3896.         jne     parse_cmdline_4
  3897.  
  3898. parse_cmdline_3:
  3899.         inc     si                      ;Move past =
  3900.         xor     bx,bx                   ;Find next char
  3901.         call    scan4char
  3902.         jc      parse_error
  3903.         mov     cmd_value,si            ;Save ptr to cmd
  3904.         mov     console_out,0           ;No screen output
  3905.         mov     bl,1
  3906.         call    scan4char               ;Find end of command
  3907.         mov     byte ptr [si],0         ;Term cmd name
  3908.                 jc      parse_cmdline_exit                              ;2.4 GS
  3909.                 xor     bl,bl
  3910.         call    scan4char               ;Find 1st param
  3911.         jc      parse_cmdline_exit
  3912. parse_cmdline_4:
  3913.         mov     bp,offset var1_value
  3914.         mov     cx,MAX_PARAMS
  3915. parse_cmdline_5:
  3916.         mov     [bp],si                 ;Save ptr to param
  3917.         add     bp,2
  3918.         inc     num_params              
  3919.  
  3920.         mov     bl,4                    ;Scan until parse char
  3921.         mov     dl,parse_char
  3922.         call    scan4char
  3923.         mov     byte ptr [si],0         ;Term param
  3924.         jc      parse_cmdline_exit
  3925.  
  3926.         cmp     [si+1],dl
  3927.         jne     parse_cmdline_6
  3928.         inc     si
  3929.         inc     si
  3930.         jmp     short parse_cmdline_7
  3931. parse_cmdline_6:
  3932.         xor     bl,bl                   ;Scan until 1st char of
  3933.         call    scan4char               ;  next param
  3934. parse_cmdline_7:
  3935.         loop    parse_cmdline_5
  3936. parse_cmdline_exit:
  3937.         clc
  3938. parse_cmdline_exit1:
  3939.         ret
  3940. parse_cmdline   endp
  3941.  
  3942. ;-----------------------------------------------------------------------
  3943. ; PARSE SWITCH  Parse command line switches
  3944. ;   Entry:  SI - Pointer to / chararacter
  3945. ;   Exit:   CF - Set if error
  3946. ;           SI - If error, points to error message string
  3947. ;-----------------------------------------------------------------------
  3948. parse_switch    proc    near
  3949.         assume  cs:code,ds:code
  3950.         inc     si                      ;Skip past '/'.
  3951.         lodsb                           ;Get cmdline switch
  3952.  
  3953.         mov     di,offset cmd_switches  
  3954.         mov     cx,offset cmd_switch_end - offset cmd_switches
  3955.         mov     bx,offset cmd_switch_end - offset cmd_switches - 1
  3956.         or      al,20h                  ;Make switch lower case
  3957.         repne   scasb
  3958.         mov     dx,offset errmsg3       ;Command not found msg
  3959.         stc
  3960.         jne     switch_exit
  3961.         sub     bx,cx                   ;Compute offset into list
  3962.         shl     bx,1                    ;Convert to word offset
  3963.         clc                             ;Assume pass
  3964.         call    cs:[bx+offset cmd_jmp_tbl] ;Call command routine.
  3965. switch_exit:
  3966.         ret
  3967. switch_master:
  3968.         mov     use_mastenv,1           ;Set use master env flag
  3969.         ret
  3970. switch_quiet:
  3971.         mov     quiet_flag,1            ;Set to suppress output
  3972.         ret
  3973. switch_pchar:
  3974.         lodsb
  3975.         mov     parse_char,al           ;Set new parse character
  3976.         ret
  3977. switch_base:
  3978.         call    asc2hex                 ;Base at 10 right now
  3979.         dec     si
  3980.         or      dx,dx                   ;Check for proper range
  3981.         jne     switch_base1
  3982.         cmp     ax,1
  3983.         jbe     switch_base1
  3984.         cmp     ax,16
  3985.         ja      switch_base1
  3986.         mov     number_base,ax          ;Set new base
  3987.         clc
  3988.         ret
  3989. switch_base1:
  3990.         mov     si,offset errmsg24      ;Base outside range
  3991.         stc
  3992.         ret
  3993. switch_help:
  3994.         mov     help_flag,1             ;Set help flag
  3995.         ret
  3996. switch_install:
  3997.         cmp     installed,0
  3998.         je      switch_install1
  3999.         mov     si,offset errmsg23
  4000.         stc
  4001.         jmp     short switch_install2
  4002. switch_install1:
  4003.         mov     install_flag,1          ;Set to install as TSR
  4004.         clc
  4005. switch_install2:
  4006.         ret
  4007. switch_remove:
  4008.         cmp     installed,0
  4009.         jne     switch_remove1
  4010.         mov     si,offset errmsg21
  4011.         stc
  4012.         jmp     short switch_remove2
  4013. switch_remove1:
  4014.         mov     remove_flag,1          ;Set to remove as TSR
  4015.         clc
  4016. switch_remove2:
  4017.         ret
  4018. parse_switch    endp
  4019.  
  4020. ;-----------------------------------------------------------------------
  4021. ; GETCOMSPEC returns the name of the command processor from the env
  4022. ;-----------------------------------------------------------------------
  4023. getcomspec      proc    near
  4024.         push    ds
  4025.  
  4026.         mov     ax,ds:[2ch]             ;Get prog environment segment
  4027.         mov     di,offset shell_var     ;Point to COMSPEC var name
  4028.         call    getenvvar               ;Get ptr to env var value
  4029.         jc      getcomspec_exit         ;CF = 1, var not found.
  4030.  
  4031.         mov     di,cs:dest_var_val      ;Copy var value to dest string
  4032.         push    di
  4033.         call    copy_string
  4034.         pop     si
  4035.         pop     ds
  4036.  
  4037.         mov     di,databuff_ptr         ;Use 2nd buff as temp buff
  4038.         call    parse_filename
  4039.         mov     si,di
  4040.         mov     bx,di
  4041. getcomspec_1:
  4042.         lodsb
  4043.         cmp     al,'\'                  ;Mark start of filename or
  4044.         jne     getcomspec_2            ;  directory.
  4045.         mov     bx,si
  4046. getcomspec_2:
  4047.         or      al,al
  4048.         je      getcomspec_3
  4049.         cmp     al,'.'
  4050.         jne     getcomspec_1
  4051.         dec     si
  4052. getcomspec_3:
  4053.         mov     cx,si
  4054.         sub     cx,bx                   ;Compute length
  4055.         cmp     cx,8
  4056.         jb      getcomspec_4
  4057.         mov     cx,8
  4058. getcomspec_4:
  4059.         mov     shell_namlen,cl         ;Save length of comspec name
  4060.         mov     di,offset shell_name
  4061.         mov     si,bx
  4062.         rep     movsb
  4063. getcomspec_exit:
  4064.         xor     ax,ax
  4065.         mov     di,dest_var_val         ;ReZero the buffer.  This is
  4066.         mov     cx,VAR_SIZE             ;  what caused the FILENAME
  4067.         rep     stosb                   ;  and FILEEXT bugs in 1.1
  4068.         clc
  4069.         ret
  4070. getcomspec      endp
  4071.  
  4072.  
  4073. ;-----------------------------------------------------------------------------
  4074. ; FILENAME STR Return only the filename from a filename string
  4075. ; Entry:  SI - Partial filename
  4076. ;         DI - Working buffer
  4077. ; Exit:   SI - Points to file name
  4078. ;         CX - Length of filename
  4079. ;-----------------------------------------------------------------------------
  4080. get_filename    proc    near
  4081.         assume  cs:code,ds:code,es:code
  4082.         call    parse_filename
  4083.         mov     si,di
  4084.         mov     bx,di
  4085. getfname_1:
  4086.         lodsb
  4087.         cmp     al,'\'                  ;Mark start of filename or
  4088.         jne     getfname_2              ;  directory.
  4089.         mov     bx,si
  4090. getfname_2:
  4091.         or      al,al
  4092.         je      getfname_3
  4093.         cmp     al,'.'
  4094.         jne     getfname_1
  4095.         mov     byte ptr ds:[si-1],0    ;Terminate 
  4096. getfname_3:
  4097.         dec     si
  4098.         mov     cx,si
  4099.         sub     cx,bx                   ;Compute length
  4100.         mov     si,bx
  4101.         ret
  4102. get_filename    endp
  4103.  
  4104. ;-----------------------------------------------------------------------
  4105. ; PARSE FILENAME  creates a proper pathname for a filename
  4106. ;   Entry:  SI - Pointer to ASCIIZ filename
  4107. ;           DI - Pointer to buffer to hold resulting pathname
  4108. ;-----------------------------------------------------------------------
  4109. parse_filename  proc    near
  4110.         assume  cs:code,ds:code,es:code
  4111.         push    di
  4112.         push    si
  4113.         cmp     dos_version,300h        ;See if DOS 3.x or greater.
  4114.         jb      parse_fname_0           ;If not, parse the old way.
  4115.         mov     ah,60h                  ;DOS Resolve Path
  4116.         int     21h
  4117.         jmp     short parse_fname_7
  4118. parse_fname_0:
  4119.         cmp     byte ptr [si+1],":"     ;See if disk specified
  4120.         je      parse_fname_1           ;Yes, skip disk assignment
  4121.  
  4122.         mov     ah,19h                  ;Get default disk
  4123.         int     21h
  4124.         inc     al
  4125.  
  4126.         mov     dl,al                   ;Save default disk number
  4127.         add     al,40h                  ;Make ASCII
  4128.         mov     ah,":"
  4129.         jmp     short parse_fname_2
  4130. parse_fname_1:
  4131.         lodsw                           ;Get disk specified
  4132.         and     al,0DFh                 ;Convert to caps
  4133.         mov     dl,al
  4134.         sub     dl,40h                  ;Convert to hex
  4135. parse_fname_2:
  4136.         stosw                           ;Load disk specification
  4137. ;Look for directory specification.
  4138.         mov     bx,di                   ;save start of path
  4139.         mov     al,"\"
  4140.         cmp     byte ptr [si],al        ;See if starting from root
  4141.         je      parse_fname_3            ;Yes, skip append of path
  4142.  
  4143.         stosb                           ;Start at root
  4144.         push    si                      ;Save current pointer
  4145.         mov     si,di                   ;Point to dest buffer
  4146.         mov     ah,47h                  ;Get default path
  4147.         int     21h
  4148.         pop     si
  4149.  
  4150.         cmp     byte ptr [di],0         ;See if NULL path
  4151.         je      parse_fname_3
  4152.  
  4153.         call    find_end                ;Scan to end of path string
  4154.         dec     di                      ;move back before zero
  4155.         mov     al,"\"                  ;Append path string with
  4156.         stosb                           ;  a \.  CX = length of path
  4157. parse_fname_3:
  4158.         add     cx,2                    ;Append filename to path.
  4159.         mov     ax,VAR_SIZE             ;Compute space remaining in
  4160.         sub     ax,cx                   ;  the destination buffer.
  4161.         xchg    cx,ax
  4162.         xor     ah,ah                   ;Clear last char holder
  4163. parse_fname_4:
  4164.         lodsb                           ;Get filename character.  If
  4165.         or      al,al                   ;  end of string, exit.
  4166.         jz      parse_fname_6           ;Else, write char.
  4167.         stosb
  4168.         cmp     ax,".."                 ;If last two chars are ..,
  4169.         jne     parse_fname_5           ;  scan backwards to delete
  4170.         std                             ;  last directory.
  4171.         sub     di,4                    ;First, backup past '\..'
  4172.         mov     al,"\"                  ;Look for directory sep
  4173.         push    cx
  4174.         mov     cx,di                   ;Compute length of path
  4175.         sub     cx,bx
  4176.         repne   scasb                   ;Now, past last directory
  4177.         pop     cx
  4178.         cld                             ;Scan forwards again
  4179.         inc     di                      ;Move back past \
  4180. parse_fname_5:
  4181.         mov     ah,al                   ;Save last character read.
  4182.         loop    parse_fname_4
  4183. parse_fname_6:
  4184.         xor     al,al                   ;Terminate string with 0
  4185.         stosb
  4186. parse_fname_7:
  4187.         pop     si
  4188.         pop     di
  4189.         ret
  4190. parse_filename  endp
  4191.  
  4192. ;-----------------------------------------------------------------------------
  4193. ; CREATE FILE Creates a new file.
  4194. ; Entry:  DX - Pointer to ASCIIZ filename.
  4195. ; Exit:   BX - File handle
  4196. ;         CF - Set if error
  4197. ;-----------------------------------------------------------------------------
  4198. create_file     proc    near
  4199.         push    cx
  4200.         mov     ah,3ch                  ;Create file
  4201.         xor     cx,cx                   ;Normal attributes
  4202.         int     21h
  4203.         mov     bx,ax                   ;Copy file handle
  4204.         pop     cx
  4205.         ret
  4206. create_file     endp
  4207.  
  4208. ;-----------------------------------------------------------------------------
  4209. ; OPEN FILE Opens a file.
  4210. ; Entry:  AL - Access flags
  4211. ;         DX - Pointer to ASCIIZ filename.
  4212. ; Exit:   BX - File handle
  4213. ;         CF - Set if error
  4214. ;-----------------------------------------------------------------------------
  4215. open_file       proc    near
  4216.         mov     ah,3dh                  ;Open file
  4217.         int     21h
  4218.         mov     bx,ax                   ;Copy file handle
  4219.         ret
  4220. open_file       endp
  4221.  
  4222. ;-----------------------------------------------------------------------------
  4223. ; CLOSE FILE Closes a file.
  4224. ; Entry:  BX - File handle
  4225. ; Exit:   CF - Set if error
  4226. ;-----------------------------------------------------------------------------
  4227. close_file      proc    near
  4228.         mov     ah,3eh                  ;Close file
  4229.         int     21h
  4230.         ret
  4231. close_file      endp
  4232.  
  4233. ;-----------------------------------------------------------------------------
  4234. ; READ FILE Reads data from a file
  4235. ; Entry:  BX - File handle
  4236. ;         CX - Number of bytes to read
  4237. ;         DX - Pointer to data buffer
  4238. ; Exit:   CF - Set if error
  4239. ;         AX - bytes read.
  4240. ;-----------------------------------------------------------------------------
  4241. read_file       proc    near
  4242.         mov     ah,3fh                  ;Read file data
  4243.         int     21h
  4244.         ret
  4245. read_file       endp
  4246.  
  4247. ;-----------------------------------------------------------------------------
  4248. ; WRITE FILE Writes data to a file
  4249. ; Entry:  BX - File handle
  4250. ;         CX - Number of bytes to write
  4251. ;         DX - Pointer to data buffer
  4252. ; Exit:   CF - Set if error
  4253. ;-----------------------------------------------------------------------------
  4254. write_file      proc    near
  4255.         mov     ah,40h                  ;Write file data
  4256.         int     21h
  4257.         ret
  4258. write_file      endp
  4259.  
  4260. ;-----------------------------------------------------------------------------
  4261. ; MOVE FILEPTR Moves the file read pointer of a file.
  4262. ; Entry:  AX,DX - Offset of file pointer
  4263. ;            BX - File handle
  4264. ;            CL - Move type, 0 = from start, 2 = from end.
  4265. ; Exit:      CF - Set if error
  4266. ;-----------------------------------------------------------------------------
  4267. move_fileptr    proc    near
  4268.         xchg    cx,dx                   ;Copy most sig word
  4269.         xchg    dx,ax                   ;Copy least sig word
  4270.         mov     ah,42h                  ;Move file pointer
  4271.         int     21h
  4272.         ret
  4273. move_fileptr    endp
  4274.  
  4275. ;-----------------------------------------------------------------------------
  4276. ; PARSE DOSERR Points SI to the proper DOS error string
  4277. ; Entry:  AL - DOS error number
  4278. ; Exit:   SI - Pointer to ASCIIZ string
  4279. ;-----------------------------------------------------------------------------
  4280. parse_doserr    proc    near
  4281.         xor     ah,ah
  4282.         cmp     al,34
  4283.         jbe     parse_doserr_1
  4284.         xor     al,al
  4285. parse_doserr_1:
  4286.         shl     ax,1
  4287.         mov     si,offset doserr_tbl
  4288.         add     si,ax
  4289.         mov     si,[si]
  4290.         stc                             ;Set error flag
  4291.         ret
  4292. parse_doserr    endp
  4293.  
  4294. ;-----------------------------------------------------------------------------
  4295. ; TRUNCNUM truncates a number to the max length of a string
  4296. ; Entry:  AX - Number to truncate
  4297. ; Exit:   AX - Truncated number
  4298. ;-----------------------------------------------------------------------------
  4299. truncnum        proc    near
  4300.         cmp     ax,VAR_SIZE             ;VAR_SIZE = max string length
  4301.         jb      trunc_1
  4302.         mov     ax,VAR_SIZE
  4303. trunc_1:
  4304.         ret
  4305. truncnum        endp
  4306.  
  4307. ;-----------------------------------------------------------------------------
  4308. ; FINDSTR  determines if a string is in a list.
  4309. ; Entry:  DS:SI - Pointer to ASCII string to find.
  4310. ;         ES:DI - Pointer to list of ASCIIZ strings.
  4311. ;            CX - Size of string
  4312. ; Exit:      DI - Pointer to entry in list
  4313. ;            CF - Clear if string found
  4314. ;            BX - If CF clear, index into list
  4315. ;-----------------------------------------------------------------------------
  4316. findstr         proc    near
  4317.         push    cx
  4318.         push    dx
  4319.         xor     dx,dx
  4320.         or      dx,cx                   ;Save length of string
  4321.         je      finds_3
  4322.         xor     bx,bx                   ;Zero index counter
  4323. finds_1:
  4324.         push    di
  4325.         push    si
  4326.         push    cx
  4327.         repe    cmpsb                   ;Compare command
  4328.         pop     cx
  4329.         pop     si
  4330.         pop     di
  4331.         clc
  4332.         je      findstr_exit
  4333.         inc     bx                      ;Inc string count
  4334.  
  4335.         push    cx
  4336.         call    find_endl               ;Find end of string.
  4337.         pop     cx
  4338.         jne     finds_3
  4339.         cmp     byte ptr es:[di],0      ;See if second zero. If so
  4340.         jne     finds_1                 ;  end of list.
  4341. finds_3:
  4342.         stc                             ;Indicate string not found
  4343. findstr_exit:
  4344.         pop     dx
  4345.         pop     cx
  4346.         ret
  4347. findstr         endp
  4348.  
  4349. ;-----------------------------------------------------------------------------
  4350. ; FIND END scans to the end of an ASCIIZ string.
  4351. ; Entry:  ES:DI - Pointer to ASCII string
  4352. ; Exit:   ES:DI - Pointers to character after string.
  4353. ;            CX - Length of string
  4354. ;            ZF - Clear if end not found in MAX length of characters
  4355. ;-----------------------------------------------------------------------------
  4356. find_end        proc    near
  4357.         push    ax
  4358.         mov     cx,VAR_SIZE
  4359.         xor     al,al
  4360.         repne   scasb
  4361.         pushf
  4362.         mov     ax,VAR_SIZE
  4363.         sub     ax,cx
  4364.         xchg    ax,cx
  4365.         dec     cx
  4366.         popf
  4367.         pop     ax
  4368.         ret
  4369. find_end        endp
  4370.  
  4371. ;-----------------------------------------------------------------------------
  4372. ; FIND ENDL scans to the end of an ASCIIZ string. String can be up to 32K
  4373. ; Entry:  ES:DI - Pointer to ASCII string
  4374. ; Exit:   ES:DI - Pointers to character after string.
  4375. ;            CX - Length of string
  4376. ;            ZF - Clear if end not found in MAX length of characters
  4377. ;-----------------------------------------------------------------------------
  4378. find_endl       proc    near
  4379.         push    ax
  4380.         mov     cx,8000h
  4381.         xor     al,al
  4382.         repne   scasb
  4383.         pushf
  4384.         mov     ax,8000h
  4385.         sub     ax,cx
  4386.         xchg    ax,cx
  4387.         dec     cx
  4388.         popf
  4389.         pop     ax
  4390.         ret
  4391. find_endl       endp
  4392.  
  4393. ;-----------------------------------------------------------------------------
  4394. ; CAPS STRING capitalizes ASCIIZ string
  4395. ; Entry:  SI - Pointer to ASCII string to capitalize
  4396. ; Exit:   CX - Length of string
  4397. ;-----------------------------------------------------------------------------
  4398. caps_string     proc near
  4399.         assume  ds:code,es:code
  4400.         push    bx
  4401.         push    dx
  4402.         mov     bx,"za"                 ;Set filter limits
  4403.         mov     dx,0df00h               ;Set character filter
  4404.         call    filter_string
  4405.         pop     dx
  4406.         pop     bx
  4407.         ret
  4408. caps_string     endp
  4409.  
  4410. ;-----------------------------------------------------------------------------
  4411. ; LC STRING makes an ASCIIZ string lower case
  4412. ; Entry:  SI - Pointer to ASCII
  4413. ; Exit:   CX - Length of string
  4414. ;-----------------------------------------------------------------------------
  4415. lc_string       proc near
  4416.         assume  ds:code,es:code
  4417.         push    bx
  4418.         push    dx
  4419.         mov     bx,"ZA"                 ;Set filter limits
  4420.         mov     dx,0ff20h               ;Set character filter
  4421.         call    filter_string
  4422.         pop     dx
  4423.         pop     bx
  4424.         ret
  4425. lc_string       endp
  4426.  
  4427. ;-----------------------------------------------------------------------------
  4428. ; FILTER STRING filters an ASCIIZ string
  4429. ; Entry: DS:SI - Pointer to ASCII string
  4430. ;           BL - Lower limit of char range
  4431. ;           BH - Upper limit of char range
  4432. ;           DL - OR  filter
  4433. ;           DH - AND filter
  4434. ; Exit:     CX - Length of string
  4435. ;-----------------------------------------------------------------------------
  4436. filter_string   proc near
  4437.         assume  ds:code,es:code
  4438.         push    si
  4439.         push    di
  4440.         push    es
  4441.  
  4442.         mov     di,si
  4443.         push    ds
  4444.         pop     es
  4445.         xor     cx,cx                   ;Clear byte counter.
  4446. filter_1:
  4447.         lodsb                           ;Get character
  4448.         or      al,al                   ;Allow any non-space character
  4449.         je      filter_exit
  4450.         cmp     al,bl                   ;If between lower and upper
  4451.         jb      filter_2                ;  char limit it.
  4452.         cmp     al,bh
  4453.         ja      filter_2
  4454.         or      al,dl                   ;Apply OR filter
  4455.         and     al,dh                   ;Apply AND filter
  4456. filter_2:
  4457.         stosb                           ;Save character
  4458.         inc     cx                      ;Inc byte counter
  4459.         jmp     short filter_1
  4460. filter_exit:
  4461.         pop     es
  4462.         pop     di
  4463.         pop     si
  4464.         ret
  4465. filter_string   endp
  4466.  
  4467. ;-----------------------------------------------------------------------------
  4468. ; COPY STRING copies an ASCIIZ string
  4469. ; Entry:  DS:SI - Pointer to source ASCIIZ string
  4470. ;         ES:DI - Pointer to destination buffer
  4471. ; Exit:   CX - Length of string
  4472. ;-----------------------------------------------------------------------------
  4473. copy_string     proc near
  4474.         assume  ds:code,es:code
  4475.         xor     cx,cx
  4476. copy_string_1:
  4477.         lodsb                           ;Move character
  4478.         stosb
  4479.         or      al,al                   ;See if end of string
  4480.         je      copy_string_exit        ;If so, exit
  4481.         inc     cx                      ;Inc count
  4482.         jmp     short copy_string_1
  4483. copy_string_exit:
  4484.         ret
  4485. copy_string     endp
  4486.  
  4487. ;-----------------------------------------------------------------------------
  4488. ; PRINT STRCR prints an ASCIIZ string then appends a CR LF to the end
  4489. ; Entry:  SI - pointer to ASCIIZ string.
  4490. ;-----------------------------------------------------------------------------
  4491. print_strcr     proc    near
  4492.         assume  ds:nothing,es:nothing
  4493.         call    print_str
  4494.         mov     si,offset endmsg
  4495.         call    print_str
  4496.         ret
  4497. print_strcr     endp
  4498.  
  4499. ;-----------------------------------------------------------------------------
  4500. ; PRINT STR  prints an ASCIIZ string to the std output device
  4501. ; Entry:  SI - Pointer to ASCIIZ string.
  4502. ;-----------------------------------------------------------------------------
  4503. print_str       proc    near
  4504.         cmp     cs:quiet_flag,0
  4505.         jne     print_str_exit
  4506.         lodsb                           ;Get character
  4507.         or      al,al                   ;See if end of string
  4508.         je      print_str_exit
  4509.         mov     ah,2                    ;DOS print character
  4510.         mov     dl,al
  4511.         int     21h                     ;Call DOS
  4512.         jmp     short print_str
  4513. print_str_exit:
  4514.         ret
  4515. print_str       endp
  4516.  
  4517. ;-----------------------------------------------------------------------------
  4518. ; HEX2ASC converts number in DX AX to ASCII
  4519. ; Entry:  DX AX - Number
  4520. ;         DI - Destination buffer
  4521. ;         CF - Clear
  4522. ; Exit:   Di - Points to byte past terminating 0
  4523. ;-----------------------------------------------------------------------------
  4524. hex2asc         proc near
  4525.         assume  ds:nothing,es:nothing
  4526.         push    ax
  4527.         push    bx
  4528.         push    cx
  4529.         push    dx
  4530.         push    si
  4531.  
  4532.         mov     si,cs:number_base       ;Load number base
  4533.         mov     bx,ax
  4534.         mov     cx,dx
  4535.         mov     dx,-1                   ;Load end of number flag
  4536.         push    dx
  4537. hex_loop1:
  4538.         xchg    ax,cx                   ;Get high word in AX
  4539.         xor     dx,dx                   ;Clear high word
  4540.         div     si                      ;Divide by base (10)
  4541.         xchg    cx,ax                   ;Save result of high divide
  4542.         xchg    ax,bx                   ;Get low word, leave remainder
  4543.         div     si                      ;  in DX.
  4544.         xchg    bx,ax                   ;Save result of low divide
  4545.  
  4546.         add     dl,30h                  ;Convert to ascii
  4547.         cmp     dl,'9'
  4548.         jbe     hex_1
  4549.         add     dl,7
  4550. hex_1:
  4551.         push    dx                      ;Save digit on stack
  4552.         or      bx,bx
  4553.         jne     hex_loop1               ;See if number = 0.  If not,
  4554.         or      cx,cx                   ;  continue divide loop.
  4555.         jne     hex_loop1
  4556.  
  4557.         mov     bl,"0"                  ;Set leading zero flag
  4558. hex_loop2:
  4559.         pop     dx                      ;Get digit off stack
  4560.         cmp     dx,-1                   ;See if end flag
  4561.         je      hex_2
  4562.         or      bl,dl                   ;Don't print leading zeros.
  4563.         cmp     bl,"0"                  ;The first non zero will
  4564.         je      hex_loop2               ;  change bl to non-zero.
  4565.         mov     al,dl                   ;Write to buffer
  4566.         stosb
  4567.         jmp     short hex_loop2
  4568. hex_2:
  4569.         cmp     bl,"0"                  ;If number zero, write last
  4570.         jne     hex_exit                ;  zero.
  4571.         mov     al,bl
  4572.         stosb
  4573. hex_exit:
  4574.         xor     al,al                   ;Termainate with zero
  4575.         stosb
  4576.         pop     si
  4577.         pop     dx
  4578.         pop     cx
  4579.         pop     bx
  4580.         pop     ax
  4581.         ret
  4582. hex2asc         endp
  4583.  
  4584. ;------------------------------------------------------------------------
  4585. ; ASC2HEX converts an ASCII number to hex
  4586. ; Entry:     SI - Pointer to ASCIIZ string
  4587. ; Exit:   DX,AX - Number
  4588. ;            CF - Set if overflow
  4589. ;------------------------------------------------------------------------
  4590. asc2hex         proc    near
  4591.         assume  ds:nothing,es:nothing
  4592.         push    bx
  4593.         push    cx
  4594.         push    di
  4595.         xor     cx,cx                   ;Zero result
  4596.         xor     di,di
  4597.         xor     bx,bx                   ;Keep BH clear
  4598. asc_loop1:
  4599.         mov     bl,[si]                 ;Get next digit
  4600.         inc     si
  4601.         cmp     bl,"9"
  4602.         jbe     asc_1
  4603.         and     bl,0dfh                 ;Make upper case
  4604.         sub     bl,7
  4605. asc_1:
  4606.         sub     bl,"0"                  ;Convert digit from ASCII to
  4607.         jb      asc_exit                ;  hex.  If digit illegal
  4608.         cmp     bx,cs:number_base       ;  char, exit.
  4609.         jae     asc_exit
  4610. asc_2:
  4611.         xchg    ax,di                   ;Shift result in DI CX by
  4612.         mul     cs:number_base          ;  the base.
  4613.         jc      asc_exit1
  4614.         xchg    di,ax
  4615.         xchg    ax,cx
  4616.         mul     cs:number_base          
  4617.         xchg    cx,ax
  4618.         add     di,dx
  4619.         jc      asc_exit1
  4620.  
  4621.         add     cx,bx                   ;Add new number to result.
  4622.         adc     di,0
  4623.         jnc     short asc_loop1
  4624. asc_exit1:
  4625.         mov     ax,cx                   ;Copy result
  4626.         mov     dx,di
  4627.         pop     di
  4628.         pop     cx
  4629.         pop     bx
  4630.         ret
  4631. asc_exit:
  4632.         clc
  4633.         jmp     short asc_exit1
  4634. asc2hex         endp
  4635.  
  4636. ;-----------------------------------------------------------------------
  4637. ; SCAN4CHAR scans a string to find the first character.
  4638. ; Entry:  SI - pointer to ASCII string
  4639. ;         BL - 0 = find next char,
  4640. ;              1 = find next space,
  4641. ;              2 = find end of line,
  4642. ;              3 = find next space or =.
  4643. ;              4 = find character in DL.
  4644. ; Exit:   AL - matching character
  4645. ;         SI - pointer to matching character
  4646. ;         CF - set if carriage return or EOF found
  4647. ;-----------------------------------------------------------------------
  4648. scan4char       proc near
  4649.         assume  ds:nothing,es:nothing
  4650. scan4loop:
  4651.         lodsb
  4652.         cmp     al,13                   ;Check for CR
  4653.         jne     scan4_1
  4654. scan4_eol:
  4655.         stc
  4656.         jmp     short scan4_exit1
  4657. scan4_1:
  4658.         cmp     bl,4
  4659.         je      scan4_dl
  4660.         cmp     bl,3
  4661.         je      scan4_equal
  4662.         cmp     bl,1                    ;Check if searching for 
  4663.         je      scan4_space             ;  space, char, or EOL.
  4664.         ja      scan4loop
  4665.         cmp     al," "                  ;Check for space or other
  4666.         jbe     scan4loop               ;  'white' characters.
  4667.         jmp     short scan4_exit
  4668. scan4_dl:
  4669.         cmp     al,dl                   ;Check for parse character
  4670.         je      scan4_exit
  4671.         or      al,al
  4672.         je      scan4_eol
  4673.         jmp     short scan4loop
  4674. scan4_equal:
  4675.         cmp     al,"="                  ;Check for exit
  4676.         je      scan4_exit
  4677. scan4_space:
  4678.         cmp     al," "                  ;Check for characters.
  4679.         ja      scan4loop
  4680. scan4_exit:
  4681.         clc
  4682. scan4_exit1:
  4683.         dec     si                      ;Back up before char
  4684.         ret
  4685. scan4char       endp
  4686.  
  4687. ;-----------------------------------------------------------------------
  4688. ; GETKEY  Waits for a keypress and returns the key.
  4689. ;-----------------------------------------------------------------------
  4690. getkey          proc    near
  4691.         call    prog_idle               ;yield
  4692.         mov     ah,1                    ;Check key status
  4693.         int     16h
  4694.         jz      getkey                  ;No key, loop
  4695.         cld                             ;Reset dir flag due to yield
  4696.  
  4697.         mov     ah,2                    ;Get shift status
  4698.         int     16h
  4699.         push    ax
  4700.         mov     ax,12ffh                ;Get extended shift status
  4701.         int     16h
  4702.         pop     bx
  4703.         cmp     bl,al                   ;See if same
  4704.         jne     getkey_1                ;No, assume old keyboard
  4705.  
  4706.         mov     ah,11h                  ;Get extended key status
  4707.         xor     al,al                   ;Clear zero flag
  4708.         int     16h
  4709.         jz      getkey_1
  4710.         mov     ax,1000h                ;Extended keyboard read
  4711.         int     16h
  4712.         jmp     short getkey_2
  4713. getkey_1:
  4714.         xor     ax,ax                   ;Get key from buffer
  4715.         int     16h
  4716. getkey_2:
  4717.         ret
  4718. getkey          endp
  4719.  
  4720. ;-----------------------------------------------------------------------
  4721. ;PROG IDLE  Indicates to the system that we are idle
  4722. ;-----------------------------------------------------------------------
  4723. prog_idle       proc    near
  4724.         push    ax
  4725.         int     28h                     ;Call Idle interrupt
  4726.         cmp     dos_version,300h
  4727.         jb      prog_idleexit
  4728.         mov     ax,1680h                ;Mux DOS idle
  4729.         int     2fh
  4730. prog_idleexit:
  4731.         pop     ax
  4732.         ret
  4733. prog_idle       endp
  4734.  
  4735. ;-----------------------------------------------------------------------
  4736. ; GETENVVAR returns a pointer to the value of an environment variable.  
  4737. ; Entry:    AX - Segment of environment
  4738. ;        DS:DI - Pointer to ASCIIZ string containing the name of env var. 
  4739. ; Exit:  DS:SI - If CF = 0, Pointer to value of environment variable 
  4740. ;           DI - If CF = 0, Pointer to start of var name in environment
  4741. ;           CF - Set if variable not found
  4742. ;-----------------------------------------------------------------------
  4743. getenvvar       proc    near
  4744.         push    ax
  4745.         push    es
  4746.         push    ax                      ;Save env segment
  4747.         push    di                      ;Append = sign to the end of
  4748.         call    find_end                ;  the variable.
  4749.         mov     word ptr es:[di-1],003dh 
  4750.         pop     si
  4751.         call    caps_string
  4752.         pop     es                      ;Use find string routine to
  4753.         xor     di,di                   ;  find the variable name.
  4754.  
  4755.         call    findstr
  4756.         jnc     getenvvar_1
  4757.         stc
  4758.         jmp     short getenvvar_exit
  4759. getenvvar_1:
  4760.         push    es                      ;DS:SI = ES:DI
  4761.         pop     ds                      
  4762.         xchg    si,di
  4763. getenvvar_2:
  4764.         lodsb                           ;Find end of var name.
  4765.         cmp     al,'='
  4766.         jne     getenvvar_2
  4767.         clc
  4768. getenvvar_exit:
  4769.         pop     es
  4770.         pop     ax
  4771.         ret
  4772. getenvvar       endp
  4773.  
  4774. ;-----------------------------------------------------------------------------
  4775. ; SETENV  Sets environment variables.
  4776. ;
  4777. ; Entry:  DS:SI - pointer to env var name
  4778. ;         ES:DI - pointer to env var value
  4779. ;-----------------------------------------------------------------------------
  4780. setenv          proc    near
  4781.         push    bp
  4782.         push    ds
  4783.         push    es
  4784.  
  4785.         push    di                      ;Save ptr to var value
  4786.         push    es
  4787.  
  4788.         call    find_end                ;Get length of var value
  4789.         mov     dx,cx                   ;Copy length
  4790.         mov     di,si
  4791.         push    ds                      ;Add length of var name plus
  4792.         pop     es                      ;  room for the equals sign.
  4793.         call    find_end
  4794.         mov     word ptr es:[di-1],003dh ;Append = sign
  4795.         inc     cx                       ;Add byte for =
  4796.         add     dx,cx
  4797.         inc     dx                      ;Add byte for terminating 0
  4798.  
  4799.         mov     ax,masterenv_seg
  4800.         cmp     use_mastenv,0
  4801.         jne     setenv_0
  4802.         mov     ax,localenv_seg
  4803. setenv_0:
  4804.         push    ax
  4805.         dec     ax
  4806.         mov     es,ax
  4807.         mov     bp,es:[3]               ;Get size of env segment
  4808.         push    cx
  4809.         mov     cl,4                    ;Convert paragraphs to bytes
  4810.         shl     bp,cl
  4811.         pop     cx
  4812.         pop     es
  4813.  
  4814.         xor     di,di                   ;Use find string routine to
  4815.         call    findstr                 ;  find the variable name.
  4816.  
  4817.         push    si
  4818.         push    ds
  4819.         jc      setenv_2                ;Var not found, skip erase
  4820.         push    es
  4821.         pop     ds
  4822.  
  4823.         mov     si,di                   ;Erase current var value by
  4824.         call    find_endl               ;  copying the next env var
  4825.         xchg    si,di                   ;  over the current one.
  4826. setenv_1:
  4827.         cmp     byte ptr [si],0
  4828.         je      setenv_2
  4829. setenv_11:
  4830.         lodsb
  4831.         stosb
  4832.         or      al,al
  4833.         jne     setenv_11
  4834.         jmp     short setenv_1
  4835. setenv_2:
  4836.         pop     ax                      ;Get ptr to var name
  4837.         pop     cx
  4838.  
  4839.         pop     ds                      ;Get ptr to var value
  4840.         pop     si
  4841.  
  4842.         cmp     byte ptr ds:[si],0      ;See if NULL variable, If so,
  4843.         je      setenv_31               ;  don't add to env block
  4844.  
  4845.         mov     bx,di                   ;Get offset of end of env
  4846.         add     bx,dx                   ;Add length of value
  4847.         inc     bx                      ;Add length of terminating byte
  4848.         cmp     bp,bx
  4849.         ja      setenv_3
  4850.  
  4851.         push    ax                      ;Save ptr to var name
  4852.         push    cx
  4853.         mov     dx,es
  4854.         dec     dx
  4855.         mov     es,dx           
  4856.         push    es:[1]                  ;Save current owner segment
  4857.         inc     dx
  4858.         mov     es,dx
  4859.         add     bx,15                   ;If no room in environemnt,
  4860.         mov     cl,4                    ;  see if env segment can be
  4861.         shr     bx,cl                   ;  resized to make room for
  4862.         mov     ah,4ah                  ;  new variable.
  4863.         int     21h                     ;Reallocate memory
  4864.         pop     bx                      ;Get old owner
  4865.         pop     cx
  4866.         pop     ax
  4867.         jc      setenv_5
  4868.         push    es
  4869.         dec     dx
  4870.         mov     es,dx
  4871.         mov     es:[1],bx               ;Restore old owner 
  4872.         pop     es
  4873. setenv_3:
  4874.         push    si
  4875.         push    ds
  4876.  
  4877.         mov     si,cx
  4878.         mov     ds,ax
  4879.         call    copy_string             ;Copy var name to env
  4880.         dec     di                      ;Back up over last zero
  4881.         pop     ds
  4882.         pop     si
  4883.  
  4884.         mov     bl,"="                  ;Since env vars can't have
  4885.         mov     bh,bl                   ;  the char '=', filter
  4886.         mov     dl,-1                   ;  string to change = to
  4887.         mov     dh,equalsub_char        ;  graphic char that looks
  4888.         call    filter_string           ;  similar.
  4889.  
  4890.         call    copy_string             ;Copy var value to env
  4891. setenv_31:
  4892.         xor     al,al
  4893.         stosb                           ;Add 2 zeros to end env.
  4894. setenv_4:
  4895.         clc                             ;Set pass flag
  4896. setenv_5:
  4897.         pop     es
  4898.         pop     ds
  4899.         pop     bp
  4900.         ret
  4901. setenv          endp
  4902.  
  4903.  
  4904. ;-----------------------------------------------------------------------------
  4905. ; REMOVE uninstalls the installed program from memory.
  4906. ;-----------------------------------------------------------------------------
  4907. remove          proc    near
  4908.         assume  cs:code,ds:code,es:code
  4909.         push    es
  4910.         mov     ax,352fh                ;Get MUX vector
  4911.         int     21h
  4912.         mov     cx,cs                   ;Get CS
  4913.         mov     ax,es                   ;Check to make sure MUX
  4914.         cmp     ax,cx                   ;  vector not modified.
  4915.         jne     remove_error
  4916.         push    ds
  4917.         mov     ax,252fh                ;Set interrupt
  4918.         lds     dx,[int2fh]             ;Get old int 2F vector
  4919.         int     21h
  4920.         pop     ds
  4921.         mov     es,ds:[2ch]             ;Get env segment
  4922.         mov     ah,49h                  ;Free mem
  4923.         int     21h
  4924.         mov     si,offset infomsg2      ;Removed message
  4925.         call    print_strcr
  4926. remove_exit:
  4927.         pop     es
  4928.         ret
  4929. remove_error:
  4930.         mov     remove_flag,0
  4931.         mov     si,offset errmsg22      ;Can't remove error msg
  4932.         stc
  4933.         jmp     short remove_exit
  4934.  
  4935. remove          endp
  4936.  
  4937.         even
  4938. end_of_resident =       $
  4939. ;=======================================================================
  4940. ;Start of nonresident data
  4941. ;=======================================================================
  4942. ;-----------------------------------------------------------------------
  4943. ; FINAL INSTALL  Last part of install process.  Must be less that
  4944. ; the resident stack size. (512 bytes)
  4945. ;-----------------------------------------------------------------------
  4946. final_install   proc    near
  4947.         mov     sp,di                   ;Set stack to res stack
  4948.         rep     stosb                   ;Clear buffer
  4949.         mov     databuff_ptr,di
  4950.  
  4951.         add     di,DATABUFF_SIZE+15
  4952.         mov     cl,4
  4953.         shr     di,cl
  4954.         mov     dx,di
  4955.         mov     ax,3100h                ;TSR
  4956.         int     21h
  4957.         mov     ax,4c01h                ;This should never happen
  4958.         int     21h
  4959. final_install   endp
  4960. ;-----------------------------------------------------------------------
  4961. ; Lookup table for help messages.  Each command has two help strings. 
  4962. ; 1. The descripion of the function.  The word 'Returns' is 
  4963. ;    automatically added to the start of the string.
  4964. ; 2. A syntax message that describes the arguements for the function.
  4965. ;
  4966. ; This table MUST be in the same order as the command table at the
  4967. ; start of the program.
  4968. ;-----------------------------------------------------------------------
  4969. help_tbl        dw      offset left_help
  4970.         dw      offset left_syntax
  4971.         dw      offset right_help
  4972.         dw      offset left_syntax
  4973.         dw      offset mid_help
  4974.         dw      offset mid_syntax
  4975.         dw      offset length_help
  4976.         dw      offset length_syntax
  4977.         dw      offset find_help        
  4978.         dw      offset find_syntax      
  4979.         dw      offset findc_help       
  4980.         dw      offset findc_syntax     
  4981.         dw      offset lower_help       
  4982.         dw      offset length_syntax    
  4983.         dw      offset upper_help       
  4984.         dw      offset length_syntax    
  4985.         dw      offset char_help        
  4986.         dw      offset char_syntax      
  4987.         dw      offset val_help         
  4988.         dw      offset add_syntax       
  4989.         dw      offset filedrive_help   
  4990.         dw      offset filename_syntax
  4991.         dw      offset filedir_help     
  4992.         dw      offset filename_syntax  
  4993.         dw      offset filename_help    
  4994.         dw      offset filename_syntax  
  4995.         dw      offset fileext_help     
  4996.         dw      offset filename_syntax  
  4997.         dw      offset parse_help
  4998.         dw      offset parse_syntax
  4999.         dw      offset commas_help
  5000.         dw      offset not_syntax
  5001.         dw      offset repeat_help
  5002.         dw      offset repeat_syntax
  5003.  
  5004.         dw      offset read_help        
  5005.         dw      offset read_syntax      
  5006.         dw      offset write_help       
  5007.         dw      offset write_syntax     
  5008.         dw      offset filesize_help    
  5009.         dw      offset filename_syntax  
  5010.         dw      offset linesize_help    
  5011.         dw      offset filename_syntax  
  5012.         dw      offset truename_help    
  5013.         dw      offset filename_syntax  
  5014.         dw      offset filedate_help
  5015.         dw      offset filename_syntax
  5016.         dw      offset filetime_help  
  5017.         dw      offset filename_syntax
  5018.                 DW      OFFSET errlvl_help                              ;2.3 CW
  5019.                 DW      OFFSET errlvl_syntax                            ;2.3 CW
  5020.  
  5021.         dw      offset ver_help 
  5022.         dw      offset no_syntax        
  5023.         dw      offset ask_help 
  5024.         dw      offset ask_syntax       
  5025.         dw      offset inwin_help       
  5026.         dw      offset no_syntax        
  5027.         dw      offset twoFcheck_help   
  5028.         dw      offset twoFcheck_syntax
  5029.         dw      offset envfree_help     
  5030.         dw      offset no_syntax        
  5031.         dw      offset envsize_help     
  5032.         dw      offset no_syntax        
  5033.         dw      offset mastervar_help   
  5034.         dw      offset mastervar_syntax
  5035.         dw      offset localvar_help    
  5036.         dw      offset mastervar_syntax 
  5037.         dw      offset truever_help
  5038.         dw      offset no_syntax
  5039.         dw      offset files_help  
  5040.         dw      offset no_syntax  
  5041.         dw      offset lastdrive_help
  5042.         dw      offset no_syntax
  5043.         dw      offset codepage_help 
  5044.         dw      offset no_syntax 
  5045.         dw      offset country_help  
  5046.         dw      offset no_syntax  
  5047.         dw      offset biosdate_help 
  5048.         dw      offset no_syntax 
  5049.         dw      offset getkey_help   
  5050.         dw      offset no_syntax   
  5051.         dw      offset locenv_help   
  5052.         dw      offset no_syntax
  5053.         dw      offset masenv_help
  5054.         dw      offset no_syntax
  5055.  
  5056.         dw      offset add_help 
  5057.         dw      offset add_syntax       
  5058.         dw      offset sub_help 
  5059.         dw      offset add_syntax       
  5060.         dw      offset mul_help 
  5061.         dw      offset add_syntax       
  5062.         dw      offset div_help 
  5063.         dw      offset div_syntax                       
  5064.         dw      offset and_help
  5065.         dw      offset add_syntax
  5066.         dw      offset or_help
  5067.         dw      offset add_syntax
  5068.         dw      offset xor_help
  5069.         dw      offset div_syntax
  5070.         dw      offset not_help
  5071.         dw      offset not_syntax
  5072.         dw      offset convert_help
  5073.         dw      offset convert_syntax
  5074.                 DW      OFFSET gt_help                                  ;2.5 CW
  5075.                 DW      OFFSET gtlt_syntax                              ;2.5 CW
  5076.                 DW      OFFSET ge_help                                  ;2.5 CW
  5077.                 DW      OFFSET gtlt_syntax                              ;2.5 CW
  5078.                 DW      OFFSET lt_help                                  ;2.5 CW
  5079.                 DW      OFFSET gtlt_syntax                              ;2.5 CW
  5080.                 DW      OFFSET le_help                                  ;2.5 CW
  5081.                 DW      OFFSET gtlt_syntax                              ;2.5 CW
  5082.  
  5083.         dw      offset peek_help
  5084.         dw      offset peek_syntax
  5085.         dw      offset poke_help
  5086.         dw      offset poke_syntax
  5087.         dw      offset in_help
  5088.         dw      offset in_syntax
  5089.         dw      offset out_help
  5090.         dw      offset out_syntax
  5091.         dw      offset interrupt_help
  5092.         dw      offset interrupt_syntax
  5093.         dw      offset scan_help
  5094.         dw      offset scan_syntax
  5095.  
  5096.         dw      offset day_help
  5097.         dw      offset day_syntax
  5098.         dw      offset month_help
  5099.         dw      offset month_syntax
  5100.         dw      offset date_help
  5101.         dw      offset date_syntax
  5102.         dw      offset time_help
  5103.         dw      offset no_syntax
  5104.                 DW      OFFSET dow_help                                 ;2.3 CW
  5105.                 DW      OFFSET no_syntax                                ;2.3 CW
  5106.  
  5107.         dw      offset totalmem_help
  5108.         dw      offset no_syntax
  5109.         dw      offset freemem_help
  5110.         dw      offset no_syntax
  5111.         dw      offset totalxms_help
  5112.         dw      offset no_syntax
  5113.         dw      offset freexms_help
  5114.         dw      offset no_syntax
  5115.         dw      offset xmsver_help
  5116.         dw      offset no_syntax
  5117.         dw      offset totalems_help
  5118.         dw      offset no_syntax
  5119.         dw      offset freeems_help
  5120.         dw      offset no_syntax
  5121.         dw      offset emsver_help 
  5122.         dw      offset no_syntax 
  5123.         dw      offset freeumb_help
  5124.         dw      offset no_syntax
  5125.  
  5126.         dw      offset strver_help
  5127.         dw      offset no_syntax
  5128.         dw      offset strinst_help
  5129.         dw      offset no_syntax
  5130.         dw      offset help_help
  5131.         dw      offset help_syntax
  5132.  
  5133. ;-----------------------------------------------------------------------
  5134. ;Help text
  5135. ;-----------------------------------------------------------------------
  5136. left_help       db      "left n characters",0
  5137. left_syntax     db      "String,  Number of chars",0
  5138. right_help      db      "right n characters",0
  5139. mid_help        db      "middle n chars",0
  5140. mid_syntax      db      "String,  Start char,  Length",0
  5141. length_help     db      "String length",0
  5142. length_syntax   db      "String",0
  5143. find_help       db      "the position of Findstring in String",0
  5144. find_syntax     db      "String, Findstring",0
  5145. findc_help      db      "the position of Findstring in String. Case sen",0
  5146. findc_syntax    db      "String, Findstring",0
  5147. lower_help      db      "string all lowercase",0
  5148. upper_help      db      "string all uppercase",0
  5149. char_help       db      "ASCII number of character",0
  5150. char_syntax     db      "Char[Char][char][char][char][char][char][char]",0
  5151. val_help        db      "ASCII char for a number",0
  5152.  
  5153. filedrive_help  db      "the drive of a filename",0
  5154. filedir_help    db      "the directory of a filename",0
  5155. filename_help   db      "the file name",0
  5156. filename_syntax db      "Filename",0
  5157. fileext_help    db      "the file extension",0
  5158. parse_help      db      "the Nth token from a string",0
  5159. parse_syntax    db      "String, Token number, Token seperator char",0
  5160. commas_help     db      "a number parsed with commas every 3 digits",0
  5161. repeat_help     db      "a string of n number of characters",0
  5162. repeat_syntax   db      "Number of chars, Char to repeat",0
  5163.  
  5164. read_help       db      "a line from a file",0
  5165. read_syntax     db      "Filename, line number",0
  5166. write_help      db      "nothing.  Appends a string to the end of a file",0
  5167. write_syntax    db      "Filename, String",0
  5168. filesize_help   db      "the size of a file",0
  5169. linesize_help   db      "the number of lines",0
  5170. truename_help   db      "the complete filename",0
  5171. filedate_help   db      "the date of a file",0
  5172. filetime_help   db      "the time of a file",0
  5173.  
  5174. ask_help        db      "a response from a user",0
  5175. ask_syntax      db      "[Prompt string][, Max chars][, 1=* echo 2=No echo]",0
  5176. ver_help        db      "the DOS version number",0
  5177. inwin_help      db      "1 if Windows running",0
  5178. twoFcheck_help  db      "status of programs hooked to the Multiplex int",0
  5179. envfree_help    db      "the bytes free in the environment",0
  5180. envsize_help    db      "the size of the environment",0
  5181. mastervar_help  db      "a variable from the Master env  ",0
  5182. mastervar_syntax db     "Variable Name",0
  5183. localvar_help   db      "a variable from the Local env   ",0
  5184.  
  5185. truever_help    db      "the true DOS verison. Requires DOS 5.0 or later",0
  5186. files_help      db      "the total number of files that can be open",0
  5187. lastdrive_help  db      "the letter of the last possible drive",0
  5188. ask2_help       db      "a response from the user",0
  5189. ask2_syntax     db      "[Prompt [,max number of chars [,no echo flag]]",0
  5190. codepage_help   db      "the active code page. Requires DOS 3.3 or later",0
  5191. country_help    db      "the country code for the system",0
  5192. biosdate_help   db      "the date for the ROM BIOS",0
  5193. getkey_help     db      "the scan code and ASCII value of the next"
  5194.         db      " key pressed",0
  5195. locenv_help     db      "the segment of the active environment",0
  5196. masenv_help     db      "the segment of the master environment",0
  5197.  
  5198. add_help        db      "the sum of the parameters",0
  5199. add_syntax      db      "Num1, Num2 [,Num3][,Num4][,Num5][,Num6]"
  5200.         db      13,10,9,9,9,9,"    [,Num7][,Num8][,Num9][,Num10]",0
  5201. sub_help        db      "the difference of two numbers",0
  5202. mul_help        db      "the product of the parameters",0
  5203. div_help        db      "the quotient of two numbers",0
  5204. div_syntax      db      "Number, Number",0
  5205. and_help        db      "the logical AND of the parameters",0
  5206. or_help         db      "the logical OR of the parameters",0
  5207. xor_help        db      "the exclusive OR of two numbers",0
  5208. not_help        db      "the logical NOT of a number",0
  5209. not_syntax      db      "Number",0
  5210. convert_help    db      "a number with the base specified",0
  5211. convert_syntax  db      "Number, New Base",0
  5212.  
  5213. peek_help       db      "a series of bytes from memory",0
  5214. peek_syntax     db      "Segment, Offset [, Number of bytes [,Word flag]]",0
  5215. poke_help       db      "nothing.  Writes up to 8 bytes to memory",0
  5216. poke_syntax     db      "Segment, Offset , Byte1[,Byte2][,Byte3][,Byte4]"
  5217.         db      "[,Byte5][,Byte6][,Byte7][,Byte8]",0
  5218. in_help         db      "a byte from an I/O port",0
  5219. in_syntax       db      "Port number",0
  5220. out_help        db      "nothing.  Writes a byte to an I/O port",0
  5221. out_syntax      db      "Port number, Output byte",0
  5222. interrupt_help  db      "registers from an interrupt.  Dangerous!",0
  5223. interrupt_syntax db     "Interrupt number, AX, BX, CX, DX,",13,10
  5224.         db      9,9,9,9,9,"  DI, SI, BP, DS, ES",0
  5225. scan_help       db      "the offset of a series of bytes in memory",0
  5226.  
  5227. scan_syntax     db      "Segment to search, Starting Offset,",13,10
  5228.         db      9,9,9,9,"     Byte1 [,Byte2] [,Byte3] [Byte4]",13,10
  5229.         db      9,9,9,9,"     [,Byte5] [,Byte6] [,Byte7] [,Byte8]",0
  5230.  
  5231. day_help        db      "the name of the current day of the week,",13,10
  5232.         db      " or corresponding to the index value",0
  5233. day_syntax      db      "[Index (1=Sunday, 2=Monday 3=Tuesday...]",0
  5234. month_help      db      "the name of the current month or the month",13,10
  5235.         db      "corresponding to the index value",0
  5236. month_syntax    db      "[Index (1=January, 2=February...]",0
  5237. date_help       db      "the current date",0
  5238. date_syntax     db      "[If present, date returned in mm-dd-yyyy format]",0
  5239. time_help       db      "the current time",0
  5240.  
  5241. totalmem_help   db      "the amount of conventional memory",0
  5242. freemem_help    db      "the largest block of free conventional memory",0
  5243. totalxms_help   db      "the amount of extended memory",0
  5244. freexms_help    db      "the amount of free extended memory",0
  5245. xmsver_help     db      "the version of the extended memory driver",0
  5246. totalems_help   db      "the amount of expanded memory",0
  5247. freeems_help    db      "the amount of free expanded memory",0
  5248. emsver_help     db      "the version of the expanded memory driver",0
  5249. freeumb_help    db      "the largest block of free Upper Memory",0
  5250.  
  5251. strver_help     db      "the version of Strings",0
  5252. strinst_help    db      "a non-zero number if Strings installed as TSR",0
  5253. help_help       db      "help text for the specified Strings command",0
  5254. help_syntax     db      "[Strings Command]"
  5255. no_syntax       db      0
  5256.  
  5257. twoFcheck_syntax db     "Number or Alias",13,10,10
  5258.         db      "    Interrupt 2F, the multiplex interrupt,"
  5259.         db      " is used by many programs to",13,10
  5260.         db      "signal that they are installed. 2FCHECK"
  5261.         db      " calls interrupt 2F with a device",13,10
  5262.         db      "number between 0 and 255.  2FCHECK returns a"
  5263.         db      " 0 if no program responds to",13,10
  5264.         db      "this device ID.  If a program does respond,"
  5265.         db      "  a non-zero number is returned.",13,10
  5266.         db      "    To prevent users from remembering a series of"
  5267.         db      " device IDs, one of the",13,10
  5268.         db      "following aliases can be used in place of the"
  5269.         db      " device number.",13,10,10
  5270.  
  5271.         db      " PRINT    - PRINT resident code         "
  5272.         db      " ASSIGN   - ASSIGN resident code",13,10
  5273.         db      " DRIVER   - DRIVER.SYS device driver    "
  5274.         db      " SHARE    - SHARE resident code",13,10
  5275.         db      " NET      - Network redirector code     "
  5276.         db      " NLS      - NLSFUNC resident code",13,10
  5277.         db      " ANSI     - ANSI.SYS device driver      "
  5278.         db      " DOSBOX   - OS/2 or Win DOS box",13,10
  5279.         db      " HIMEM    - HIMEM.SYS memory manager    "
  5280.         db      " DOSKEY   - DOSKEY resident code",13,10
  5281.         db      " GRAPHTBL - GRAFTABL resident code      "
  5282.         db      " APPEND   - APPEND resident code",13,10
  5283.         db      " DISPLAY  - DISPLAY.SYS",0
  5284.  
  5285. dow_help        DB      "the day of the week (1=Sunday)",0              ;2.3 CW
  5286. errlvl_help     DB      "the errorlevel of filename",0                  ;2.3 CW
  5287. errlvl_syntax   DB      "Filename [parameters]",0                       ;2.3 CW
  5288. gt_help         DB      "a 1 if Num1 is greater than Num2",0            ;2.5 CW
  5289. lt_help         DB      "a 1 if Num1 is less than Num2",0               ;2.5 CW
  5290. ge_help        DB      "a 1 if Num1 if greater than or equal to Num2",0 ;2.5 CW
  5291. le_help        DB      "a 1 if Num1 if less than or equal to Num2",0    ;2.5 CW
  5292. gtlt_syntax     DB      "Num1, Num2",0                                  ;2.5 CW
  5293.  
  5294. infomsg1        db      "Installed",0
  5295.  
  5296. ;-----------------------------------------------------------------------
  5297. ;INITIALIZE - Start of non resident code.
  5298. ;-----------------------------------------------------------------------
  5299. initialize      proc    near
  5300.         assume  cs:code,ds:code,es:code
  5301.         cld                             ;Set string ops 'up.'
  5302.         mov     word ptr [entry],0
  5303.         mov     ah,30h                  ;Get DOS version, run only
  5304.         int     21h                     ;  if 2.0 or greater.
  5305.         xchg    al,ah                   ;Swap major, minor numbers
  5306.         mov     dos_version,ax
  5307.         cmp     ah,2
  5308.         jae     init_1
  5309.         mov     si,offset program
  5310.         call    print_strcr
  5311.         mov     si,offset errmsg0       ;Bad DOS version
  5312.         call    print_strcr
  5313.         mov     al,1
  5314.         jmp     short init_exit
  5315. init_1:
  5316.         call    check4xms               ;Chk extended mem mgr
  5317.         mov     xms_version,ax
  5318.         call    check4ems               ;Chk expanded mem mgr
  5319.         mov     ems_version,ax
  5320.  
  5321.         mov     di,TRANS_STACK          ;Set up data buffers
  5322.         mov     sp,di                   ;Set stack
  5323.         mov     dest_var_val,di
  5324.         xor     ax,ax
  5325.         mov     cx,VAR_SIZE
  5326.         rep     stosb
  5327.         mov     databuff_ptr,di
  5328.  
  5329.         add     di,DATABUFF_SIZE+15
  5330.         mov     cl,4
  5331.         shr     di,cl
  5332.         mov     bx,di
  5333.         mov     ah,4ah                  ;Reduce memory allocation
  5334.         int     21h
  5335.         jnc     init_21
  5336.         mov     al,-1                   ;Set out of memory code
  5337.         jmp     init_exit
  5338. init_21:
  5339.         call    getcomspec              ;Get the name of the shell 
  5340.         call    getname                 ;Get the name of the prog
  5341.         call    findenv                 ;Use parent's env by def
  5342.         jc      init_4
  5343.         mov     localenv_seg,ax
  5344. init_4:
  5345.         call    findmaster              ;Find master env
  5346.         jc      init_5
  5347.         mov     masterenv_seg,ax
  5348. init_5:
  5349.         call    main                    ;Program, do your stuff
  5350.         cmp     install_flag,0          ;See if we should install
  5351.         je      init_exit
  5352.         call    install                 ;If we return, error
  5353.         call    print_strcr             ;Print error
  5354. init_exit:
  5355.         mov     ah,4Ch                  ;Terminate
  5356.         int     21h
  5357. initialize      endp
  5358.  
  5359. ;-----------------------------------------------------------------------
  5360. ; INSTALL  Installs Strings as a TSR
  5361. ;-----------------------------------------------------------------------
  5362. install         proc    near
  5363.         assume  cs:code,ds:code,es:code
  5364.         mov     ax,31eh
  5365.         cmp     ax,dos_version          ;See if DOS 3.3 
  5366.         jbe     install_1
  5367.         call    seterr0msg              ;Error, not DOS 3.3
  5368.         ret
  5369. install_1:
  5370.         
  5371.         mov     ax,352fh                ;Get interrupt 2F (MUX)
  5372.         int     21h                     ;  vector.
  5373.         mov     word ptr [int2fh],bx
  5374.         mov     word ptr [int2fh+2],es
  5375.         push    cs
  5376.         pop     es
  5377.         mov     ax,252fh                ;Point int 2F to internal
  5378.         mov     dx,offset muxint        ;  routine.
  5379.         int     21h
  5380.  
  5381.         mov     si,offset infomsg1
  5382.         call    print_strcr
  5383.  
  5384.         mov     installed,1             ;Set installed flag
  5385.         mov     di,RES_STACK            ;Set up data buffers
  5386.         mov     dest_var_val,di
  5387.         xor     ax,ax
  5388.         mov     cx,VAR_SIZE
  5389.         jmp     final_install
  5390. install         endp
  5391.  
  5392. ;-----------------------------------------------------------------------
  5393. ; GETNAME  Copies the name of the program to the name buffer
  5394. ;-----------------------------------------------------------------------
  5395. getname         proc    near
  5396.         assume  cs:code,ds:code,es:code
  5397.         push    es
  5398.         mov     ax,300h
  5399.         cmp     dos_version,300h        ;See if DOS 3.0 or later
  5400.         jb      getname_exit
  5401.  
  5402.         mov     ax,ds:[2ch]             ;Get env segment
  5403.         push    ax
  5404.         dec     ax
  5405.         mov     es,ax
  5406.         assume  es:nothing
  5407.         mov     cx,es:[3]               ;Get env seg size
  5408.         shl     cx,1
  5409.         shl     cx,1
  5410.         shl     cx,1
  5411.         shl     cx,1
  5412.         pop     es                      ;Get back env seg
  5413.         xor     ax,ax
  5414.         mov     di,ax
  5415. getname_1:
  5416.         repnz   scasb                   ;Scan env for 00
  5417.         jne     getname_exit
  5418.         cmp     byte ptr es:[di],0
  5419.         jne     getname_1
  5420.         add     di,3                    ;Move past cnt byte
  5421.         mov     si,databuff_ptr         ;Use file buffer
  5422.         xchg    di,si
  5423.         assume  ds:nothing
  5424.         push    ds                      ;Copy the filename
  5425.         push    es                      ;  into a local
  5426.         pop     ds                      ;  buffer to avoid
  5427.         pop     es                      ;  segment probs
  5428.         call    copy_string             ;  with called procs.
  5429.  
  5430.         mov     ax,cs
  5431.         mov     ds,ax
  5432.         mov     es,ax
  5433.         assume  ds:code,es:code
  5434.         mov     si,databuff_ptr
  5435.         mov     di,si
  5436.         add     di,100h
  5437.         call    get_filename
  5438.         mov     strings_namelen,cx      ;Save length
  5439.         mov     di,offset strings_name
  5440.         call    copy_string
  5441. getname_exit:
  5442.         pop     es
  5443.         ret
  5444. getname         endp
  5445.  
  5446. ;-----------------------------------------------------------------------
  5447. ; CHKARENA  Verifys a memory arena header.
  5448. ; Entry:   AX - Memory block to verify
  5449. ; Exit:    BX - Owner of memory block
  5450. ;          CX - Size of memory block
  5451. ;          CF - Clear if valid arena header
  5452. ;          ZF - Clear if last memory block
  5453. ;-----------------------------------------------------------------------
  5454. chkarena        proc    near
  5455.         assume  cs:code,ds:code,es:code,ss:code
  5456.         push    ax
  5457.         push    es
  5458.  
  5459.         dec     ax
  5460.         mov     es,ax
  5461.         mov     bx,es:[1]               ;Get owner of block
  5462.         mov     cx,es:[3]               ;Get size of block
  5463.         cmp     byte ptr es:[0],"M"     ;See if proper signature
  5464.         je      chkarena_exit           ;ZF set, CF clear if match
  5465.         cmp     byte ptr es:[0],"Z"     ;See if last blk sig
  5466.         jne     chkarena_error
  5467.         or      ax,ax                   ;Clear ZF, Clear CF
  5468. chkarena_exit:
  5469.         pop     es
  5470.         pop     ax
  5471.         ret
  5472. chkarena_error:
  5473.         stc
  5474.         jmp     short chkarena_exit
  5475. chkarena        endp
  5476.  
  5477. ;-----------------------------------------------------------------------
  5478. ; FINDCMDPSP  Finds the PSP of the command processor
  5479. ; Exit:    AX - Segment of command processor PSP 
  5480. ;-----------------------------------------------------------------------
  5481. findcmdpsp      proc    near
  5482.         assume  cs:code,ds:code,es:code,ss:code
  5483.         push    dx
  5484.         push    es
  5485. findcmdpsp_1:
  5486.         mov     ax,es:[16h]             ;Get parent's PSP
  5487.         call    chkarena                ;See if valid memory block
  5488.         jc      findcmdpsp_error
  5489.         mov     es,ax
  5490.         cmp     ax,es:[16h]             ;See if PSP is own parent
  5491.         jne     findcmdpsp_1            ;No, keep looking
  5492.         clc
  5493. findcmdpsp_exit:
  5494.         pop     es
  5495.         pop     dx
  5496.         ret
  5497. findcmdpsp_error:
  5498.         stc
  5499.         jmp     short findcmdpsp_exit
  5500. findcmdpsp      endp
  5501.  
  5502. ;-----------------------------------------------------------------------
  5503. ; FINDPSPENV  Finds the environment block for a COMMAND.COM PSP
  5504. ; Entry:   AX - Segment of PSP
  5505. ; Exit:    AX - Segment of environment
  5506. ;-----------------------------------------------------------------------
  5507. findpspenv      proc    near
  5508.         assume  cs:code,ds:code,es:code,ss:code
  5509.         push    bx
  5510.         push    es
  5511.  
  5512.         mov     dx,ax                   ;Save PSP segment
  5513.         mov     es,ax
  5514.         mov     ax,es:[2ch]             ;Get ptr to environment
  5515.         call    chkarena                ;See if valid memory block
  5516.         jc      findpspenv_1
  5517.         cmp     dx,bx                   ;See if owned by cmd.com
  5518.         jne     findpspenv_1
  5519.         jmp     short findpspenv_3
  5520. findpspenv_1:
  5521.         mov     ax,dx                   ;Get original PSP
  5522.         call    chkarena                ;Compute size of segment
  5523.         jc      findpspenv_error
  5524. findpspenv_2:
  5525.         add     ax,cx                   ;Add size of memory block
  5526.         inc     ax
  5527.         call    chkarena
  5528.         jc      findpspenv_error
  5529.         jnz     findpspenv_error        ;Env never last env block
  5530.         cmp     bx,dx                   ;See if owned by CMD.COM
  5531.         jne     findpspenv_2            ;Yes, exit
  5532. findpspenv_3:
  5533.         clc
  5534. findpspenv_exit:
  5535.         pop     es
  5536.         pop     bx
  5537.         ret
  5538. findpspenv_error:
  5539.         stc
  5540.         jmp     short findpspenv_exit
  5541. findpspenv      endp
  5542.  
  5543. ;-----------------------------------------------------------------------
  5544. ; FINDENV  Finds the parent's environment block.
  5545. ; Exit:    AX - Segment of local command processor environment.
  5546. ;-----------------------------------------------------------------------
  5547. findenv         proc    near
  5548.         assume  cs:code,ds:code,es:code,ss:code
  5549.         call    findcmdpsp              ;Get PSP of command.com
  5550.         jc      findenv_error
  5551.         call    findpspenv              ;Find environment for PSP
  5552.         jc      findenv_error
  5553. findenv_exit:
  5554.         ret
  5555. findenv_error:
  5556.         mov     si,offset errmsg16      ;Environment not found
  5557.         jmp     short findenv_exit
  5558. findenv         endp
  5559.  
  5560. ;-----------------------------------------------------------------------
  5561. ; FINDMASTER  Finds the master environment block.
  5562. ; Exit:    AX - Segment of master environment block.
  5563. ;-----------------------------------------------------------------------
  5564. findmaster      proc    near
  5565.         assume  cs:code,ds:code,es:code,ss:code
  5566.         push    di
  5567.         push    es
  5568.  
  5569.         mov     ah,52h                  ;Get address of first MCB
  5570.         int     21h
  5571.         mov     ax,es:[bx-2]            ;point ES to MCB
  5572. findmaster_1:
  5573.         inc     ax
  5574.         call    chkarena                ;See if valid mem block
  5575.         jc      findmaster_error
  5576.         jnz     findmaster_error
  5577.         cmp     ax,bx                   ;See if PSP block
  5578.         je      findmaster_2
  5579.         add     ax,cx                   ;No, add size to move 2 next
  5580.         jmp     short findmaster_1
  5581. findmaster_2:
  5582.         cmp     dos_version,0a00h       ;If OS/2, use DOS 3.3 method.
  5583.         jae     findmaster_3
  5584.         cmp     dos_version,0400h       ;If DOS 4.00 or greater,
  5585.         jb      findmaster_3            ;  COMMAND.COM may not be the
  5586.         push    ax
  5587.         dec     ax
  5588.         mov     es,ax                   ;  first program loaded.  Look
  5589.         pop     ax
  5590.         push    si
  5591.         mov     si,offset shell_name    ;  at the name of the program
  5592.         mov     di,8                    ;  stored in the last 8 bytes
  5593.         xor     cx,cx                   ;  of the memory control
  5594.         mov     cl,shell_namlen         ;  block.  If the name of the
  5595.         repe    cmpsb                   ;  command processor isn't 
  5596.         pop     si
  5597.         jne     findmaster_1            ;  found, keep looking.
  5598.         cmp     shell_namlen,8          ;If name shorter than 8 chars
  5599.         je      findmaster_3            ;  check for trailing zero.
  5600.         cmp     byte ptr es:[di],0
  5601.         jne     findmaster_1
  5602. findmaster_3:
  5603.         call    findpspenv              ;Find environment for PSP
  5604. findmaster_exit:
  5605.         pop     es
  5606.         pop     di
  5607.         ret
  5608. findmaster_error:
  5609.         mov     si,offset errmsg16      ;Environment not found
  5610.         stc
  5611.         jmp     short findmaster_exit
  5612. findmaster      endp
  5613.  
  5614. ;-----------------------------------------------------------------------
  5615. ; CHECK4XMS  Checks to see if an extended memory driver is loaded
  5616. ; Exit:  CF - Clear if ext driver found
  5617. ;        AX - EXT Version if CF clear
  5618. ;        SI - Points to error message if CF set
  5619. ;-----------------------------------------------------------------------
  5620. check4xms       proc    near
  5621.         mov     ax,4300h                ;Extended mem drvr chk
  5622.         int     2fh
  5623.         or      al,al                   ;See if loaded
  5624.         je      check4xms_error
  5625.         push    es              
  5626.         mov     ax,4310h                ;Get driver entry pt
  5627.         int     2fh
  5628.         mov     word ptr [xms_serv],bx
  5629.         mov     word ptr [xms_serv+2],es
  5630.         pop     es
  5631.         xor     ax,ax
  5632.         call    ds:[xms_serv]           ;Get version number
  5633.         mov     bx,ax                   ;Version num returned
  5634.         shr     al,1                    ;  as BCD.  Convert
  5635.         shr     al,1                    ;  to std DOS format
  5636.         shr     al,1                    ;  of maj in AH and
  5637.         shr     al,1                    ;  minor in AL
  5638.         mov     ah,10
  5639.         mul     ah
  5640.         and     bl,0fh
  5641.         add     al,bl
  5642.         mov     ah,bh
  5643.         clc
  5644. check4xms_exit:
  5645.         ret
  5646. check4xms_error:
  5647.         stc
  5648.         xor     ax,ax
  5649.         mov     si,offset errmsg19      ;ext mem not available
  5650.         jmp     short check4xms_exit
  5651. check4xms       endp
  5652.  
  5653. ;-----------------------------------------------------------------------
  5654. ; CHECK4EMS  Checks to see if an expanded memory driver is loaded
  5655. ; Exit:  CF - Clear if EMS driver found
  5656. ;        AX - EMS Version if CF clear
  5657. ;        SI - Points to error message if CF set
  5658. ;-----------------------------------------------------------------------
  5659. check4ems       proc    near
  5660.         push    es
  5661.         push    di
  5662.         mov     ax,3567h                ;Get interrupt 67 vector
  5663.         int     21h
  5664.         mov     di,0ah
  5665.         mov     si,offset ems_header
  5666.         mov     cx,8
  5667.         repe    cmpsb
  5668.         pop     di
  5669.         pop     es
  5670.         jne     check4ems_error
  5671.         mov     ah,40h                  ;Get status
  5672.         int     67h
  5673.         or      ah,ah
  5674.         jne     check4ems_error
  5675.         mov     ah,46h                  ;Get version
  5676.         int     67h
  5677.         or      ah,ah
  5678.         jne     check4ems_error
  5679.         mov     bl,al                   ;Convert ver number
  5680.         shl     ax,1
  5681.         shl     ax,1
  5682.         shl     ax,1
  5683.         shl     ax,1
  5684.         mov     al,bl
  5685.         and     ax,0f0fh
  5686.         clc
  5687. check4ems_exit:
  5688.         ret
  5689. check4ems_error:
  5690.         stc
  5691.         xor     ax,ax
  5692.         mov     si,offset errmsg17      ;EMS not available
  5693.         jmp     short check4ems_exit
  5694. check4ems       endp
  5695.  
  5696.         even                            ;Set stack on word boundry
  5697. end_of_code     =       $
  5698.  
  5699. code            ends
  5700.  
  5701. end             entry
  5702.